Подтвердить что ты не робот

Модели в Zend Framework

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

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

$foo = new User;

$foo->fetchAll()

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


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

4b9b3361

Ответ 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);