Моделирование объектов с несколькими отношениями таблиц в Zend Framework
Я играю с Zend Framework и пытаюсь использовать руководство "QuickStart" против веб-сайта, которое я делаю, чтобы посмотреть, как этот процесс будет работать. Простите меня, если этот ответ очевиден, мы надеемся, что кто-то из вас может пролить свет на это.
У меня есть три таблицы базы данных:
CREATE TABLE `users` (
`id` int(11) NOT NULL auto_increment,
`email` varchar(255) NOT NULL,
`username` varchar(255) NOT NULL default '',
`first` varchar(128) NOT NULL default '',
`last` varchar(128) NOT NULL default '',
`gender` enum('M','F') default NULL,
`birthyear` year(4) default NULL,
`postal` varchar(16) default NULL,
`auth_method` enum('Default','OpenID','Facebook','Disabled') NOT NULL default 'Default',
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
CREATE TABLE `user_password` (
`user_id` int(11) NOT NULL,
`password` varchar(16) NOT NULL default '',
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
CREATE TABLE `user_metadata` (
`user_id` int(11) NOT NULL default '0',
`signup_date` datetime default NULL,
`signup_ip` varchar(15) default NULL,
`last_login_date` datetime default NULL,
`last_login_ip` varchar(15) default NULL,
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Я хочу создать модель User, которая использует все три таблицы в определенных ситуациях. Например, к таблице метаданных можно получить доступ, если/когда метаданные необходимы. Доступ к таблице user_password осуществляется только в том случае, если установлен параметр auth_method по умолчанию. Скорее всего, я добавлю таблицу профилей позже, чтобы получить доступ к пользовательской модели.
Каков наилучший способ сделать это с ZF и почему?
Ответы
Ответ 1
class Users extends Zend_Db_Table_Abstract
{
protected $_name = 'users';
protected $_rowClass = 'User';
protected $_dependentTables = array ('UserMetadata', 'UserPassword');
...
class UserMetadata extends Zend_Db_Table_Abstract
{
protected $_name = 'user_metadata';
protected $_referenceMap = array (
'Users'=> array (
'columns'=>'user_id',
'refTableClass'=>'Users',
'refColumns'=>'id'
)
);
...
class UserPassword extends Zend_Db_Table_Abstract
{
protected $_name = 'user_password';
protected $_referenceMap = array (
'Users'=> array (
'columns'=>'user_id',
'refTableClass'=>'Users',
'refColumns'=>'id'
)
);
Получение данных:
$id = //get your user id from somewhere
$users = new Users();
$user = $users->fetchRow('id=?', $id);
if ($user->authMethod == 0)
{
$metadata = $user->findDependentRowset('UserMetadata')->current();
}
или
$user = $users->fetchRow($users->select()
->where('gender=?, 'M')
->order('email ASC');
... и т.д.
Вставка данных:
$newRow = $users->fetchNew();
$newRow->email = [email protected];
$newRow->save();
или
$users = new Users();
$data = array('email' => '[email protected]',
'firstname' => 'Me');
$users->insert($data);
Обновление:
$user->email = '[email protected]';
$user->save();
Удаление строки:
$user->delete();
Использование транзакции:
$db->beginTransaction();
$db->commit();
$db->rollback();
и т.д. все это в Руководство ZF!
Ответ 2
В основном вместо использования Zend_Db_Table
для получения данных используйте более общие Zend_Db_Select
или Zend_Db_Statement
.
BTW. Возможно, вам захочется получить доступ к данным пароля не непосредственно в модели пользователя, а скорее в вашем пользовательском классе auth, полученном из Zend_Auth_Adapter
.
Ответ 3
В двух словах я бы создал модель для каждой таблицы, а не одну модель, которая обращается ко всем трем. Я бы тогда определить отношения между таблицами.
Чтобы быть честным, кажется, что не очень "СУХОЙ" нужно создать модель для каждой таблицы, но это то, что я вижу неоднократно в различных примерах онлайн, и это то, что я сделал в нескольких проектах, которые у меня есть созданный с помощью Zend Framework. Если у кого-то есть лучший способ справиться с этим, я надеюсь, что он разместит его здесь.
Ответ 4
Я бы сказал, что лучший способ сделать это с ZF можно с помощью Doctrine.
Ответ 5
Всего несколько заметок прямо с места в карьер:
Первая таблица пользователей выглядит скорее как таблица Person, за исключением метода auth, но вы можете поместить ее в таблицу User_Password, которую вы, вероятно, могли бы переименовать User. Похоже, что таблица User_Metadata просто объединяется с таблицей User_Password/User.
Теперь, даже без этих изменений, у вас есть три разные таблицы с тремя различными понятиями, если вы моделируете каждый из этих разделов как разные классы, а затем у вас есть класс UserModel как вид фасада для доступа к ним, это, скорее всего, сделайте это легче.