Intereting Posts

Модели в Zend Framework

Каковы некоторые из способов реализации моделей в Zend Framework?

Я видел, что основной class User extends Zend_Db_Table_Abstract а затем накладывает на него вызовы в ваших контроллерах:

$foo = new User;

$foo->fetchAll()

но как насчет более сложных применений? Раздел Quickstart документации предлагает такой пример, но я все еще чувствую, что не получаю пример «наилучшего использования» для моделей в Zend Framework. Какие-нибудь интересные реализации там?


EDIT: Я должен уточнить (в ответ на комментарий CMS) … Я знаю о более сложных выборах. Меня интересовали общие подходы к концепции модели и конкретные примеры того, как их реализовали другие (в основном, материал, из которого вышло руководство, и материал, который имеет базовый принцип работы)

Я лично подклассифицирую как 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. (Вот несколько моих мыслей и ссылок на эту тему .) Этот подход действительно немного тяжелый, но я считаю, что он держит контроллеры сосредоточенными на обработке ввода и координации с представлением; оставляя модель для выполнения конкретной работы приложения.

Я работал на Zend и довольно много работал над компонентом Zend_Db_Table.

Zend Framework не дает большого руководства по концепции «модели» в отношении шаблона модели домена. Для модели нет базового класса, поскольку модель инкапсулирует часть бизнес-логики, специфичную для вашего приложения. Я написал блог об этом предмете более подробно.

Устойчивость к базе данных должна быть внутренней реализацией модели. Модель обычно использует одну или несколько таблиц. Это распространенный, но ненадлежащий объектно-ориентированный дизайн, чтобы рассматривать модель как расширение таблицы. Другими словами, следует сказать, что модель HAS-A Table – не модель IS-A Table.

Это пример IS-A:

 class MyModel extends Zend_Db_Table_Abstract { } 

Это пример HAS-A:

 class MyModel // extends nothing { protected $some_table; } 

В реальной модели домена вы должны использовать $ some_table в методах MyModel.

Вы также можете прочитать мнение Мартина Фаулера о шаблоне проектирования модели домена , а также его описание антипаттерна модели анонимного домена , а именно то, как многие разработчики, к сожалению, подходят к программированию OO.

Никогда не используйте Zend_Db_Table в качестве вашей модели. Это просто беспокоит вас. Либо вы пишете свои собственные классы моделей, которые используют Zend_Db_Table, чтобы поговорить с вашей базой данных, либо вы можете прочитать мой блог здесь для взлома, который позволяет вам в некоторой степени объединить класс Model и Zend_Db_Table.

Главное не в том, что когда вы используете Zend_Db_Table прямо в своих контроллерах, вы в конечном итоге делаете одни и те же вещи в нескольких местах. Если вам нужно внести изменения в эту логику, вам нужно внести изменения в несколько мест. Нехорошо. Мой первый профессиональный проект был выполнен так, потому что я был тем, кто должен был научиться использовать ZF, и теперь это полный беспорядок.

Я также склонны писать вспомогательные функции в свои классы для сложных наборов. Somthing как $ table-> doNameFetchAll () или $ table-> doOrderFetchAll ().

Я занимался некоторыми исследованиями по Модели для ZF и наткнулся на интересную серию статей Мэтью Вейера О'Пинни, которые стоит проверить:

  • Использование Zend_Form в ваших моделях
  • Применение ACL к моделям
  • Модельная инфраструктура

Это не «производственный код», и многое осталось для воображения, но оно хорошо читается и помогло мне совсем немного.

Модель не имеет ничего общего с базой данных . Что делать, если я получаю данные из RSS-канала или службы SOAP или чтения файлов из FS?

Я помещал все эти вещи в модели. В этом случае мой класс модели может не расширять ничего . Я собираюсь написать модель, которая использует методы других моделей.

Пропустите ZF для части моделей, есть намного лучшие решения. «M» в «MVC» ZF практически отсутствует. Читая их документы, они действительно не упоминают модели вообще – это хорошо, значит, вы можете использовать практически все, что захотите, не написав много кода адаптера.

Взгляните на Doctrine для моделей. Он быстро становится фактическим ORM для PHP.

Вы можете выполнять более сложные запросы, проверьте раздел расширенного использования на странице руководства Zend_Db_Table .

 $select = $table->select(); $select->from($table, array('COUNT(reported_by) as `count`', 'reported_by')) ->where('bug_status = ?', 'NEW') ->group('reported_by'); 

вы можете расширить класс 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-архитектор для программирования с помощью zend framework» Cal Evans. книга очень информативна и проста в чтении. главы 4 и 6 будут полезны для этого.

Объект базы данных не является единственным компонентом модели. Таким образом, на самом деле не имеет смысла говорить о моделях (во множественном числе). В вашем приложении есть одна модель, которая содержит множество компонентов. Некоторые из этих компонентов могут быть табличными шлюзами (и, следовательно, простираются от Zend_Db ), а другие – нет.

Я рекомендую вам получить книгу « Driven Driven Design» от Эрика Эванса, которая отлично справляется с объяснением того, как построить объектную модель.

Я использую Propel 1.3 вместо Zend_Db_Table. Это сложно настроить, но удивительно. Он может проверять вашу базу данных и автоматически генерировать все ваши модели. Он фактически генерирует 2 уровня и 2 типа модели.

Примеры таблицы «пользователь»:

Уровень 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); 

http://zfsite.andreinikolov.com/2008/08/zend_db_table-time-overhead-about-25-percents/

Бит уловки 22, Zend_Table в принципе хорош, но генерирует некоторые служебные накладные расходы (без кэширования) …