Статьи

Zend Framework с нуля — Модели и Интеграция Доктрины ORM

Готовы вывести свои навыки PHP на новый уровень? В этой новой серии «С нуля» мы сосредоточимся исключительно на Zend Framework — полнофункциональном PHP-фреймворке, созданном Zend Technologies. Этот второй урок из нашей серии называется «Модели и интеграция доктрины ORM».


Добро пожаловать в наш Zend Framework из серии Scratch ! В нашем последнем уроке мы узнали некоторые основные вещи о Zend Framework, такие как:

  • Где скачать последние файлы Zend Framework
  • Где и как его настроить локально
  • Создание вашего первого проекта Zend Framework и настройка VirtualHost на вашем веб-сервере
  • Как именно Zend Framework реализует шаблон MVC и стандартную маршрутизацию приложений
  • Передача данных из контроллера в его представление
  • Создание макета для всего сайта для вашего приложения Zend Framework
  • Создание новых контроллеров и действий

Если вы еще этого не сделали, вам следует прочитать предыдущее руководство . Это действительно облегчит вам понимание некоторых основ Zend Framework и поможет вам понять некоторые вещи, которые мы обсудим в этом руководстве.

Во второй части этой серии мы поговорим о важной части любого веб-приложения — МОДЕЛЯХ . Мы также рассмотрим, как интегрировать очень популярный Doctrine ORM с нашим проектом Zend Framework, и выясним, почему его гораздо лучше использовать, чем родной Zend Framework Zend_Db . Итак, без лишних слов, давайте начнем!


Когда я начал пытаться понять концепцию MVC, я прочитал немало аналогий, в которых попытался объяснить, что конкретно представляет каждый из этих компонентов. Одна из лучших аналогий, которые я читал до сих пор, была из этой статьи, Другой способ думать о MVC . Это выглядит примерно так:

Итак, давайте представим банк.

Сейф — это база данных — здесь хранятся все самые важные вкусности, и они хорошо защищены от внешнего мира.

Тогда у нас есть банкиры или в программном плане модели . Банкиры — единственные, кто имеет доступ к сейфу (БД). Они, как правило, толстые, старые и ленивые, что очень хорошо следует одному из правил MVC: * толстые модели , тощие контроллеры *. Мы увидим, почему и как эта аналогия применима чуть позже.
Теперь у нас есть среднестатистические банковские работники, суслики, бегуны, контролеры. Контроллеры или суслики бегают, поэтому они должны быть стройными и худыми. Они берут добычу или информацию у банкиров ( Модели ) и передают ее клиентам банка.

Банкиры ( Модели ) были на работе некоторое время, поэтому они принимают все важные решения. Что приводит нас к другому правилу: * сохранить как можно больше бизнес-логики в модели *. Контролеры, наши среднестатистические работники, не должны принимать такие решения, они спрашивают у банкира подробности, получают информацию и передают ее клиенту (представление). Следовательно, мы продолжаем следовать правилу * жирных моделей , тощих контроллеров *. Суслики не принимают важных решений, но они не могут быть просто тупыми (поэтому небольшая бизнес-логика в контроллере в порядке). Однако, как только суслик начинает слишком много думать, банкир расстраивается и ваш банк (или ваше приложение) выходит из бизнеса. Итак, еще раз, всегда помните, чтобы перенести как можно больше бизнес-логики (или принятия решений) в модель.

Теперь банкиры уверены, что, черт возьми, они не собираются напрямую общаться с клиентами (вид), они слишком важны в своих удобных креслах для этого. Таким образом, соблюдается другое правило: * Модели не должны общаться с представлениями *. Эта связь между банкиром и клиентом (модель и представление) всегда обрабатывается сусликом (контроллером). (Да, есть некоторые исключения из этого правила для супер VIP-клиентов, но пока давайте придерживаться основ).

Бывает и так, что одному работнику (контролеру) приходится получать информацию от нескольких банкиров , и это вполне приемлемо. Однако, если банкиры связаны друг с другом (в противном случае, как они могли бы получить такую ​​хорошую работу?)… Банкиры ( Модели ) сначала будут общаться друг с другом, а затем передавать накопительную информацию своему суслику, который с радостью доставит ее клиенту ( Посмотреть). Итак, вот еще одно правило: * Связанные модели предоставляют информацию контроллеру через их ассоциации (отношения) *.

Так что насчет нашего клиента (вид)? Банки совершают ошибки, и клиент должен быть достаточно умен, чтобы сбалансировать свой счет и принять некоторые решения. В терминах MVC мы получаем еще одно простое правило: * вполне допустимо, чтобы представления содержали некоторую логику, которая касается представления или представления *. Следуя нашей аналогии, клиент не забудет надеть брюки, когда они идут в банк, но они не собираются рассказывать банкирам, как обрабатывать транзакции.

В двух словах:

  • Модели являются представителями базы данных и должны быть там, где находится вся бизнес-логика приложения.
  • Контроллеры связываются с моделями и просят их получить необходимую им информацию.
  • Эта информация затем передается контроллером в представление и отображается
  • Очень редко модель напрямую взаимодействует с представлением, но иногда это может происходить при необходимости
  • Модели могут общаться с другими моделями и не являются самодостаточными. У них есть отношения, которые переплетаются друг с другом
  • Эти отношения облегчают и ускоряют получение информации контроллером, поскольку он не должен взаимодействовать с различными моделями — модели могут делать это сами

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


Первое, что нам нужно сделать, это подключить наше приложение Zend к базе данных. К счастью, команда zf может позаботиться об этом. Откройте командную строку (или терминал), cd в папку thenextsocial и введите следующее:

1
zf configure db-adapter «adapter=PDO_MYSQL&dbname=thenextsocial&host=localhost&username=[your local database username]&password=[your local database password]» -s development

Если все правильно, вы должны получить вывод, похожий на:

1
A db configuration for the development section has been written to the application config file.

Кроме того, вы должны увидеть две новые строки в вашем файле application.ini :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
resources.db.adapter = «PDO_MYSQL»
resources.db.params.dbname = «thenextsocial»
resources.db.params.host = «localhost»
resources.db.params.username = «[your local database username]»
resources.db.params.password = «[your local database password]»
</p></code>
 
<h3>The application.ini explained</h3>
<p>The <code>application.ini</code> is a configuration file which should contain all of the configuration we have for an application.
 
<div class=»tutorial_image»>
<img src=»http://nettuts.s3.amazonaws.com/1122_zend2/images/application_ini.png» alt=»The application.ini file» title=»The application.ini file» />
 
<small>The <code>application.ini</code> file</small>
</div>
 
<p>I’m sure you’ve noticed that the <code>application.ini</code> file has sections enclosed in [square brackets].
 
<p>To add to that, you can &ldquo;inherit&rdquo;
 
<p>To configure our project to use the <code>development</code> configuration settings, open or create an <strong>.htaccess</strong> file inside the <strong>public_html</strong> folder, and make sure that it looks like this:</p>
 
[php]
SetEnv APPLICATION_ENV development
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ — [NC,L]
RewriteRule ^.*$ index.php [NC,L]

Мы ясно видим, что директива SetEnv APPLICATION_ENV устанавливает среду нашего приложения. Если и когда мы переместим приложение в другую среду, это должно быть единственное, что нам нужно изменить. Это гарантирует, что все, на что наше приложение работает, определено в application.ini , что гарантирует, что наше приложение не полагается на какие-либо внешние настройки. Это помогает устранить проблему «она работает на моей машине для разработки, почему она не работает на рабочем сервере?» .


Прежде чем мы создадим вашу первую модель для приложения, нам понадобится база данных, которую модель будет представлять первой. Давайте начнем с чего-то простого — таблицы User , где мы сохраним всех зарегистрированных пользователей для TheNextSocial .

Войдите в свою базу данных MySQL и создайте базу данных под названием thenextsocial . После создания выполните следующий запрос для создания таблицы User и прилагаемой таблицы User Settings :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CREATE TABLE `thenextsocial`.`user` (
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` VARCHAR(100) NOT NULL,
  `password` TEXT NOT NULL,
  `salt` TEXT NOT NULL,
  `date_created` DATETIME NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `Index_email`(`email`)
)
ENGINE = InnoDB
CHARACTER SET utf8 COLLATE utf8_general_ci;
 
CREATE TABLE `thenextsocial`.`user_settings` (
  `id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
  `user_id` INTEGER UNSIGNED NOT NULL,
  `name` VARCHAR(100) NOT NULL,
  `value` TEXT NOT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT `FK_user_settings_user_id` FOREIGN KEY `FK_user_settings_user_id` (`user_id`)
    REFERENCES `user` (`id`)
    ON DELETE CASCADE
    ON UPDATE CASCADE
)
ENGINE = InnoDB
CHARACTER SET utf8 COLLATE utf8_general_ci;

Эти SQL-запросы должны создавать две таблицы. Пользовательская таблица со следующими столбцами:

  • id — уникальный идентификатор для каждого пользователя
  • email — адрес электронной почты пользователя, также уникальный
  • парольпароль пользователя, который мы будем хэшировать
  • соль — случайная соль, которую мы будем использовать для хеширования пароля пользователя
  • date_created — дата и время создания пользовательской записи

И таблица user_settings , где мы будем хранить любые пользовательские настройки со столбцами:

  • id — уникальный идентификатор для каждого параметра
  • user_iduser_id который является внешним ключом для user.id
  • name — строка текста, представляющая настройку
  • значение — значение настройки

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

Теперь, когда у нас есть несколько таблиц для игры, давайте узнаем, как создать нашу первую модель: модель пользователя .


Как и во многих приложениях, обычный способ использования моделей моделей в Zend Framework — это использование популярного шаблона проектирования, называемого шаблоном «DAO». В этом шаблоне у нас есть следующие компоненты:

  • Table Data Gateway (DataSource), который соединяет наше приложение с источником данных, таблицей MySQL
  • Data Mapper (DataAccessObject), который отображает данные, извлеченные из базы данных, в
  • Объект данных (Data), который представляет строку из нашей базы данных, после того, как DataMapper отобразит в нее данные

Начнем с создания шлюза табличных данных для таблицы User с помощью инструмента zf CLI:

1
2
3
zf create db-table User user
Creating a DbTable at thenextsocial/application/models/DbTable/User.php
Updating project profile ‘thenextsocial/.zfproject.xml’

zf create db-table принимает два параметра:

  • ClassName — название класса
  • database_table — имя таблицы

Откройте файл User.php находящийся в папке application/models/DbTable и он должен выглядеть следующим образом:

1
2
3
4
5
6
7
8
9
<?php
 
class Application_Model_DbTable_User extends Zend_Db_Table_Abstract
{
 
    protected $_name = ‘user’;
 
 
}

Теперь давайте создадим класс Data Mapper . Опять же, используя инструмент zf CLI:

1
2
3
zf create model UserMapper
Creating a model at thenextsocial/application/models/UserMapper.php
Updating project profile ‘thenextsocial/.zfproject.xml’

Файл UserMapper.php будет пустым прямо сейчас, но мы добавим немного кода позже. Сейчас нам нужно создать объект данных , который является моделью User :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
zf create model User
Creating a model at thenextsocial/application/models/User.php
Updating project profile ‘thenextsocial/.zfproject.xml’
</p></code>
 
<p>Now that we have all three components of the DAO pattern, we create the code for the files.
 
[php]
<?php
class Application_Model_UserMapper
{
    protected $_db_table;
     
    public function __construct()
    {
        //Instantiate the Table Data Gateway for the User table
        $this->_db_table = new Application_Model_DbTable_User();
    }
     
    public function save(Application_Model_User $user_object)
    {
        //Create an associative array
        //of the data you want to update
        $data = array(
            ’email’ => $user_object->email,
            ‘password’ => $user_object->password,
        );
         
        //Check if the user object has an ID
        //if no, it means the user is a new user
        //if yes, then it means you’re updating an old user
        if( is_null($user_object->id) ) {
            $data[‘salt’] = $user_object->salt;
            $data[‘date_created’] = date(‘Ymd H:i:s’);
            $this->_db_table->insert($data);
        } else {
            $this->_db_table->update($data, array(‘id = ?’ => $user_object->id));
        }
    }
     
    public function getUserById($id)
    {
        //use the Table Gateway to find the row that
        //the id represents
        $result = $this->_db_table->find($id);
         
        //if not found, throw an exsception
        if( count($result) == 0 ) {
            throw new Exception(‘User not found’);
        }
         
        //if found, get the result, and map it to the
        //corresponding Data Object
        $row = $result->current();
        $user_object = new Application_Model_User($row);
         
        //return the user object
        return $user_object;
    }
}

Здесь у нас есть три метода:

  • __construct () — конструктор для класса. После создания он создает экземпляр шлюза табличных данных и сохраняет его
  • save (Application_Model_User $ user_object) — принимает Application_Model_User и сохраняет данные из объекта в базу данных
  • getUserById ($ id) — принимает целочисленный $id который представляет одну строку из таблицы базы данных, извлекает ее, затем возвращает Application_Model_User с сопоставленными данными

Откройте User.php и вставьте следующий код в:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php
class Application_Model_User
{
    //declare the user’s attributes
    private $id;
    private $email;
    private $password;
    private $salt;
    private $date_created;
     
    //upon construction, map the values
    //from the $user_row if available
    public function __construct($user_row = null)
    {
        if( !is_null($user_row) && $user_row instanceof Zend_Db_Table_Row ) {
            $this->id = $user_row->id;
            $this->email = $user_row->email;
            $this->password = $user_row->password;
            $this->salt = $user_row->salt;
            $this->date_created = $user_row->date_created;
        }
    }
     
    //magic function __set to set the
    //attributes of the User model
    public function __set($name, $value)
    {
        switch($name) {
            case ‘id’:
                //if the id isn’t null, you shouldn’t update it!
                if( !is_null($this->id) ) {
                    throw new Exception(‘Cannot update User\’s id!’);
                }
                break;
            case ‘date_created’:
                //same goes for date_created
                if( !is_null($this->date_created) ) {
                    throw new Exception(‘Cannot update User\’s date_created’);
                }
                break;
            case ‘password’:
                //if you’re updating the password, hash it first with the salt
                $value = sha1($value.$this->salt);
                break;
        }
         
        //set the attribute with the value
        $this->$name = $value;
    }
     
    public function __get($name)
    {
        return $this->$name;
    }
}
  • __construct ($ user_row) — принимает необязательный объект Zend_Db_Table_Row , который представляет одну строку из базы данных, и отображает данные в себя
  • __set ($ name, $ value) — магическая функция, которая заботится о настройке всех атрибутов для модели.
  • __get ($ name) — магическая функция, которая заботится о получении атрибута модели.

Давайте попробуем это! Если вы следовали предыдущему руководству, у вас должен быть файл IndexController.php . Откройте его и вставьте этот код, который создает нового пользователя:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public function indexAction()
{
    // action body
    $this->view->current_date_and_time = date(‘M d, Y — H:i:s’);
     
    $user = new Application_Model_User();
    $user->email = ‘[email protected]’;
    $user->salt = sha1(time());
    $user->password = ‘test’;
    $user->date_created = date(‘Ymd H:i:s’);
     
    $user_mapper = new Application_Model_UserMapper();
    $user_mapper->save($user);
}

Теперь перейдите на http://thenextsocial.local/ . Как только он загрузится, проверьте таблицу thenextsocial.user на MySQL и, если все работает, у вас должна быть новая запись User !

A new User record!

Новая запись User !

Теперь давайте попробуем обновить эту запись. Вернитесь к IndexController.php и обновите код, чтобы он соответствовал следующему:

01
02
03
04
05
06
07
08
09
10
public function indexAction()
{
    // action body
    $this->view->current_date_and_time = date(‘M d, Y — H:i:s’);
     
    $user_mapper = new Application_Model_UserMapper();
    $user = $user_mapper->getUserById(1);
    $user->email = ‘[email protected]’;
    $user_mapper->save($user);
}

Проверьте таблицу MySQL еще раз, и вы должны увидеть, что адрес электронной почты для записи был обновлен!

Updated User record

Обновленная запись User

Поздравляем! Вы успешно создали свою первую модель Zend Framework !


На веб-сайте Doctrine ORM http://doctrine-project.org/projects/orm :

Объектно-реляционный маппер (ORM) для PHP, расположенный на мощном уровне абстракции базы данных (DBAL). Одной из его основных функций является возможность писать запросы к базе данных на проприетарном объектно-ориентированном диалекте SQL под названием Doctrine Query Language (DQL), вдохновленном Hibernates HQL. Это предоставляет разработчикам мощную альтернативу SQL, которая поддерживает гибкость без необходимости дублирования кода.

По сути, библиотека Doctrine ORM абстрагирует большую часть, если не всю реализацию модели для приложения. Вот некоторые из невероятных преимуществ, которые я обнаружил при использовании Doctrine с Zend Framework:

  • Очень прост в использовании, гарантированно сократит время разработки вдвое
  • Работает так же хорошо с различными типами БД с минимальными необходимыми настройками. Например, Doctrine упростила для меня перенос приложения, над которым я работал ранее, с использованием MySQL на MSSQL
  • Инструмент скаффолдинга, называемый Doctrine_Cli который очень быстро создает модели из базы данных.

Для начала вам следует сначала загрузить библиотеку Doctrine ORM с их сайта. Я буду использовать версию 1.2.4 . Перейдите по адресу http://www.doctrine-project.org/projects/orm/1.2/download/1.2.4 и нажмите ссылку Скачать пакет 1.2.4 .

Downloading the Doctrine ORM

Загрузка Доктрины ОРМ

После загрузки откройте его и извлеките содержимое. Внутри вы должны увидеть папку Doctrine-1.2.4 и файл package.xml . Зайдите в папку, и вы увидите папку Doctrine, файл Doctrine.php и файл LICENSE .

Doctrine download contents

Doctrine скачать содержимое

Скопируйте папку Doctrine и файл Doctrine.php и поместите его в путь включения вашей установки PHP. Если вы помните, как мы настраивали Zend Framework из предыдущего урока, то, скорее всего, это та же папка, в которую вы поместили файлы библиотеки Zend .

Doctrine library with Zend library in PHP's include_path

Библиотека Doctrine с библиотекой Zend в PHP include_path

Теперь мы готовы интегрировать его с нашим приложением Zend! Начните с повторного открытия application.ini и добавления следующей конфигурации в блок [development : production] :

01
02
03
04
05
06
07
08
09
10
11
;Doctrine settings
resources.doctrine.connection_string = «mysql://[replace with db username]:[replace with db password]@localhost/thenextsocial»
resources.doctrine.models_path = APPLICATION_PATH «/models»
resources.doctrine.generate_models_options.pearStyle = true
resources.doctrine.generate_models_options.generateTableClasses = true
resources.doctrine.generate_models_options.generateBaseClasses = true
resources.doctrine.generate_models_options.classPrefix = «Model_»
resources.doctrine.generate_models_options.baseClassPrefix = «Base_»
resources.doctrine.generate_models_options.baseClassesDirectory =
resources.doctrine.generate_models_options.classPrefixFiles = false
resources.doctrine.generate_models_options.generateAccessors = false

Теперь, когда мы настроили нашу конфигурацию, откройте файл Bootstrap.php приложения. Вы найдете это в thenextsocial/application .

Bootstrap.php позволяет нам инициализировать любые ресурсы, которые мы могли бы использовать в нашем приложении. По сути, все ресурсы, которые нам нужны, должны быть размещены здесь. Мы углубимся в это более подробно позже в этой серии, но сейчас все, что вам нужно знать, это то, что формат методов здесь такой:

1
2
3
4
protected function _initYourResource()
{
    //Do your resource setup here
}

Внутри файла Bootstra.php добавьте следующий код для инициализации Doctrine с приложением:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    public function _initDoctrine()
    {
        //require the Doctrine.php file
        require_once ‘Doctrine.php’;
         
        //Get a Zend Autoloader instance
        $loader = Zend_Loader_Autoloader::getInstance();
         
        //Autoload all the Doctrine files
        $loader->pushAutoloader(array(‘Doctrine’, ‘autoload’));
         
        //Get the Doctrine settings from application.ini
        $doctrineConfig = $this->getOption(‘doctrine’);
         
        //Get a Doctrine Manager instance so we can set some settings
        $manager = Doctrine_Manager::getInstance();
         
        //set models to be autoloaded and not included (Doctrine_Core::MODEL_LOADING_AGGRESSIVE)
        $manager->setAttribute(
            Doctrine::ATTR_MODEL_LOADING,
            Doctrine::MODEL_LOADING_CONSERVATIVE);
             
        //enable ModelTable classes to be loaded automatically
        $manager->setAttribute(
            Doctrine_Core::ATTR_AUTOLOAD_TABLE_CLASSES,
            true
        );
         
        //enable validation on save()
        $manager->setAttribute(
            Doctrine_Core::ATTR_VALIDATE,
            Doctrine_Core::VALIDATE_ALL
        );
         
        //enable sql callbacks to make SoftDelete and other behaviours work transparently
        $manager->setAttribute(
            Doctrine_Core::ATTR_USE_DQL_CALLBACKS,
            true
        );
         
        //not entirely sure what this does 🙂
        $manager->setAttribute(
            Doctrine_Core::ATTR_AUTO_ACCESSOR_OVERRIDE,
            true
        );
 
        //enable automatic queries resource freeing
        $manager->setAttribute(
            Doctrine_Core::ATTR_AUTO_FREE_QUERY_OBJECTS,
            true
        );
         
        //connect to database
        $manager->openConnection($doctrineConfig[‘connection_string’]);
         
        //set to utf8
        $manager->connection()->setCharset(‘utf8’);
         
        return $manager;
    }
     
    protected function _initAutoload()
    {
        // Add autoloader empty namespace
        $autoLoader = Zend_Loader_Autoloader::getInstance();
        $resourceLoader = new Zend_Loader_Autoloader_Resource(array(
            ‘basePath’ => APPLICATION_PATH,
            ‘namespace’ => »,
            ‘resourceTypes’ => array(
                ‘model’ => array(
                    ‘path’ => ‘models/’,
                    ‘namespace’ => ‘Model_’
                )
            ),
        ));
        // Return it so that it can be stored by the bootstrap
        return $autoLoader;
    }
}

Настройки, которые я здесь выполнил, основаны на сценарии, который я нашел в прошлом на http://dev.juokaz.com , и который поддерживал Юозас Казюкенас, один из членов команды проекта Doctrine. К сожалению, блог уже закрыт, поэтому я не смогу на него ссылаться. Также обратите внимание, что у нас есть другой метод с именем _initAutoload() . Это в основном инициализирует Zend Autoloader, который будет автоматически загружать все сгенерированные модели в папке models . Это избавляет нас от необходимости включать эти файлы один за другим.

Затем нам нужно настроить сценарий командной строки Doctrine, который мы будем использовать для автоматической генерации моделей из базы данных. Вернитесь к thenextsocial папке и создайте папку с именем scripts . Внутри создайте файл с именем doctrine-cli.php и поместите в него следующее:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?php
/**
 * Doctrine CLI script
 *
 * @author Juozas Kaziukenas ([email protected])
 */
 
define(‘APPLICATION_ENV’, ‘development’);
define(‘APPLICATION_PATH’, realpath(dirname(__FILE__) . ‘/../application’));
 
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . ‘/../library’),
    ‘./’,
    get_include_path(),
)));
 
require_once ‘Zend/Application.php’;
 
// Create application, bootstrap, and run
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH .
);
 
$application->getBootstrap()->bootstrap(‘doctrine’);
 
// set aggressive loading to make sure migrations are working
Doctrine_Manager::getInstance()->setAttribute(
    Doctrine::ATTR_MODEL_LOADING,
    Doctrine_Core::MODEL_LOADING_AGGRESSIVE
);
 
$options = $application->getBootstrap()->getOptions();
 
$cli = new Doctrine_Cli($options[‘doctrine’]);
 
$cli->run($_SERVER[‘argv’]);

Вернитесь внутрь к папке с вашими models и удалите имеющиеся у нас файлы пользовательских моделей (если хотите, вы можете сначала переместить их в другое место, но их не должно быть внутри папки). Затем откройте командную строку (или терминал), cd в папку scripts и введите следующую команду:

1
php doctrine-cli.php

Вы должны увидеть что-то вроде этого:

Expected Doctrine CLI output

Ожидаемый вывод CLI Doctrine

Если все получилось, начнем создавать модели! Введите следующее:

1
php doctrine-cli.php generate-models-db

Теперь вы должны увидеть следующий вывод:

Generating Models using Doctrine CLI

Генерация моделей с использованием Doctrine CLI

Если вы это сделали, проверьте папку с вашими models раз, и вы увидите несколько совершенно новых моделей User и UserSettings , сгенерированных Doctrine!

Generated Models!

Сгенерированные модели!

Если вы откроете файлы, вы не увидите много внутри. Большая часть кода для моделей абстрагируется от библиотеки Doctrine. Расширяя класс Doctrine_Record , мы получили много готовых методов из библиотеки. IndexController.php откройте IndexController.php и замените старый тестовый код следующим:

01
02
03
04
05
06
07
08
09
10
11
12
public function indexAction()
{
    // action body
    $this->view->current_date_and_time = date(‘M d, Y — H:i:s’);
     
    $user = new Model_User();
    $user->email = ‘[email protected]’;
    $user->password = ‘test’;
    $user->salt = sha1(time());
    $user->date_created = date(‘Ymd H:i:s’);
    $user->save();
}

После этого вернитесь на http: //thenextsocial.local . Если страница загружается, проверьте таблицу MySQL, и вы увидите, что была добавлена ​​новая запись о User !

User record via Doctrine ORM

Запись User через Doctrine ORM

Теперь давайте попробуем несколько более сложных вещей — извлечение существующего User помощью встроенных методов Doctrine и его обновление. Обновите код так, чтобы он выглядел так:

1
2
3
4
5
6
7
8
9
public function indexAction()
{
    // action body
    $this->view->current_date_and_time = date(‘M d, Y — H:i:s’);
     
    $user = Doctrine_Core::getTable(‘Model_User’)->findOneByEmailAndPassword(‘[email protected]’, ‘test’);
    $user->password = ‘new_password’;
    $user->save();
}

Метод findOneByEmailAndPassword() — это удобный метод, предварительно созданный Doctrine, чтобы упростить выбор одной строки из базы данных. Самое замечательное в этом то, что вы можете смешивать и сопоставлять столбцы таблицы в методе. Например, вы можете вызвать что-то вроде findOneByIdAndNameAndPasswordAndSalt() и оно все равно будет работать!

Updating a User record via Doctrine ORM

Обновление User записи через Doctrine ORM

Теперь мы можем сделать намного больше, используя Doctrine ORM для реализации модели приложения. Такие вещи, как Doctrine Query Language (DQL) , использующие преимущества отношений между моделями и генерирующие модели из YAML . В оставшейся части серии мы будем использовать Doctrine ORM для реализации приложения в модели, так что вы фактически изучите две вещи в серии вместо одной! Гол!


К настоящему времени вы должны знать следующее:

  • Что такое «модели»
  • Подключение вашего Zend-приложения к базе данных
  • Как работает application.ini
  • Шаблон проектирования DAO
  • Создание моделей с использованием инструмента ZF CLI
  • Где скачать Doctrine ORM и как его установить
  • Интеграция Doctrine ORM с вашим приложением Zend
  • Bootstrap.php
  • Генерация моделей с помощью инструмента Doctrine CLI
  • Основное использование моделей, созданных с помощью Doctrine

Теперь, когда вы знаете, как реализовать Модели в приложении на основе Zend Framework, у вас есть знания для создания динамических веб-сайтов. Попробуйте поиграться с приложением, создайте несколько новых контроллеров и моделей, которые читают, обновляют, сохраняют и удаляют из базы данных.

В нашем следующем уроке мы узнаем о некоторых часто используемых компонентах библиотеки Zend Framework, компонентах Zend_Auth и Zend_Acl и создадим систему аутентификации TheNextSocial !

До этого следите за обновлениями и помните, что весь код, используемый здесь, доступен в репозитории TheNextSocial GitHub !