Модели в Zend Framework
Каковы некоторые из способов, которыми вы реализовали модели в Zend Framework?
Я видел базовый class User extends Zend_Db_Table_Abstract
, а затем ввел вызовы в свои контроллеры:
$foo = new User;
$foo->fetchAll()
но как насчет более сложных применений? Раздел Quickstart документации предлагает такой пример, но я все еще чувствую, что не получаю пример "наилучшего использования" для моделей в Zend Framework. Какие-нибудь интересные реализации там?
EDIT: Я должен уточнить (в ответ на комментарий CMS)... Я знаю о более сложных выборах. Меня интересовали общие подходы к концепции модели и конкретные примеры того, как их реализовали другие (в основном, материал, из которого вышло руководство, и материал, который обычно используется для замазывания)
Ответы
Ответ 1
Я лично подклассифицирую как Zend_Db_Table_Abstract
, так и Zend_Db_Table_Row_Abstract
. Основное различие между моим кодом и вашим заключается в том, что явным образом рассматриваю подкласс Zend_Db_Table_Abstract
как "таблицу" и Zend_Db_Table_Row_Abstract
как "строку". Очень редко я вижу прямые вызовы для выбора объектов, SQL или встроенных методов базы данных ZF в моих контроллерах. Я пытаюсь скрыть логику запроса конкретных записей на вызовы за Zend_Db_Table_Abstract
следующим образом:
class Users extends Zend_Db_Table_Abstract {
protected $_name = 'users';
protected $_rowClass = 'User'; // <== THIS IS REALLY HELPFUL
public function getById($id) {
// RETURNS ONE INSTANCE OF 'User'
}
public function getActiveUsers() {
// RETURNS MULTIPLE 'User' OBJECTS
}
}
class User extends Zend_Db_Table_Row_Abstract {
public function setPassword() {
// SET THE PASSWORD FOR A SINGLE ROW
}
}
/* CONTROLLER */
public function setPasswordAction() {
/* GET YOUR PARAMS */
$users = new Users();
$user = $users->getById($id);
$user->setPassword($password);
$user->save();
}
Существует множество способов приблизиться к этому. Не думайте, что это единственный, но я стараюсь следовать намерению дизайна ZF. (Вот несколько моих мыслей и ссылок на тему.) Этот подход действительно немного тяжелый, но я чувствую, что он держит контроллеры сосредоточенными на обработке ввода и координации с точки зрения; оставляя модель для выполнения конкретной работы приложения.
Ответ 2
Я работал на Zend и довольно много работал над компонентом Zend_Db_Table.
Zend Framework не дает большого руководства по концепции "модели" в отношении шаблона модели домена. Нет базового класса для модели, поскольку модель инкапсулирует часть бизнес-логики, специфичную для вашего приложения. Я написал blog об этом предмете более подробно.
Устойчивость к базе данных должна быть внутренней деталью реализации Модели. Модель обычно использует одну или несколько таблиц. Это общий, но ненадлежащий объектно-ориентированный дизайн для рассмотрения Модели как расширения таблицы. Другими словами, мы должны сказать таблицу модели HAS-A, а не таблицу IS-A.
Это пример IS-A:
class MyModel extends Zend_Db_Table_Abstract
{
}
Это пример HAS-A:
class MyModel // extends nothing
{
protected $some_table;
}
В реальной модели домена вы должны использовать $some_table в методах MyModel.
Вы также можете прочитать, как Мартин Фаулер использует шаблон дизайна Модель домена и его описание Anemic Domain Model antipattern, к какому числу разработчиков, к сожалению, подходит программирование OO.
Ответ 3
Никогда не используйте Zend_Db_Table в качестве модели. Это просто беспокоит вас. Либо вы пишете свои собственные классы моделей, которые используют Zend_Db_Table, чтобы поговорить с вашей базой данных, либо вы можете прочитать мое сообщение в блоге здесь для взлома, который позволяет вам несколько сочетают класс Model и Zend_Db_Table.
Главное не в том, что, когда вы используете Zend_Db_Table прямо в своих контроллерах, вы в конечном итоге делаете одни и те же вещи в нескольких местах. Если вам нужно внести изменения в эту логику, вам нужно внести изменения в несколько мест. Нехорошо. Мой первый профессиональный проект был выполнен так, потому что я был тем, кто должен был научиться использовать ZF, и теперь это полный беспорядок.
Я также предпочитаю писать вспомогательные функции в свои классы для сложных наборов. Somthing, как $table- > doNameFetchAll() или $table- > doOrderFetchAll().
Ответ 4
Я занимался некоторыми исследованиями по Модели для ZF и наткнулся на интересную серию статей Мэтью Вейера О'Пинни, которые стоит проверить:
Это не "производственный код", и многое осталось для воображения, но оно хорошо читается и помогло мне совсем немного.
Ответ 5
У модели нет ничего общего с базой данных. Что делать, если я получаю данные из RSS-канала или службы SOAP или чтения файлов из FS?
Я помещал все эти вещи в модели. В этом случае мой класс модели может не расширять ничего. Я собираюсь написать модель, которая использует методы других моделей.
Ответ 6
Пропустите ZF для части моделей, есть гораздо лучшие решения. "M" в ZF "MVC" в значительной степени отсутствует. Читая их документы, они вообще не упоминают модели - это хорошо, это означает, что вы можете использовать практически все, что захотите, не написав много кода адаптера.
Посмотрите Doctrine для моделей. Он быстро становится фактическим ORM для PHP.
Ответ 7
Вы можете выполнять более сложные запросы, в разделе Advanced use в Zend_Db_Table
.
$select = $table->select();
$select->from($table,
array('COUNT(reported_by) as `count`', 'reported_by'))
->where('bug_status = ?', 'NEW')
->group('reported_by');
Ответ 8
вы можете расширить класс Zend_Db_Table_Abstract и добавить к нему полезные методы. например, вы можете добавить метод changePassword() в свой пользовательский класс и манипулировать его данными. или вы можете изменить метод __toString() по умолчанию для своего класса, поэтому у вас будет настроенный метод __toString(), который, вернее, вернет всю контактную информацию пользователя (имя, адрес, номер телефона) в хорошо отформатированной строке, в вашем конструкторе вы можете заполнить свои данные в свойствах вашего объекта. затем используйте их как:
public function __toString() {
$data = $this->_name . ', ' . $this->_adderss . ', call: ' . $this->_phone;
return $data;
}
ваша модель расширяет Zend_Db_Table_Abstract только для облегчения процесса доступа к своим данным, но функциональность, которую вы могли бы иметь на этих данных, зависит от вашего творчества и необходимости.
Я рекомендую вам книгу "php | architect guide to programming with zend framework" от Cal Evans. книга очень информативна и проста в чтении. главы 4 и 6 будут полезны для этого.
Ответ 9
Объект базы данных не является единственным видом компонента модели. Таким образом, на самом деле не имеет смысла говорить о моделях (во множественном числе). В вашем приложении есть одна модель, содержащая множество компонентов. Некоторые из этих компонентов могут быть табличными шлюзами (и, следовательно, простираются от Zend_Db
), а другие - нет.
Я рекомендую вам получить книгу Domain Driven Design от Эрика Эванса, которая отлично справляется с объяснением того, как построить объектная модель.
Ответ 10
Я использую Propel 1.3 вместо Zend_Db_Table.
Это сложно настроить, но удивительно.
Он может проверять вашу базу данных и автоматически генерировать все ваши модели.
Он фактически генерирует 2 уровня и 2 типа модели.
Примеры таблицы 'user':
Уровень 1: BaseModel и BasePeer: они перезаписываются каждый раз, когда вы восстанавливаете ORM. то есть BaseUser.php и BaseUserPeer.php
Уровень 2: StubModel и StubPeer: они не перезаписываются. Это те, которые вы настраиваете. то есть User.php и UserPeer.php
Тип 1: Модель - для основных операций CRUD, а не запросов, то есть User.php
Тип 2: одноранговый - для запросов. Это статические объекты. то есть UserPeer.php
Итак, чтобы создать пользователя:
$derek = new User();
$derek->setFirstName('Derek');
$derek->save();
Чтобы найти все дереки:
$c = new Criteria();
$c->add(UserPeer::FIRST_NAME, 'Derek');
$dereks = UserPeer::doSelect($c);
Ответ 11
http://zfsite.andreinikolov.com/2008/08/zend_db_table-time-overhead-about-25-percents/
Бит уловки 22, Zend_Table в принципе хорош, но генерирует некоторые служебные накладные расходы (без кеширования)...