Отправляет email-рассылки с помощью сервиса Sendsay

PHP 5: Новые возможности.

  Все выпуски  

ZEND FRAMEWORK: Быстрый старт


Вниманию читателей!

Отдельные выпуски рассылки в той или иной мере взаимосвязаны; особенно, это относится к материалам практических занятий.

С предыдущими выпусками Вы можете ознакомиться:

  1. в архиве рассылки (оригиналы выпусков);
  2. на сайте рассылки (исправленные и дополненные версии).

Кроме того, для чтения в онлайне доступен сборник статей, составленный на основе выпусков рассылки.

# # #

Вы также можете подписаться на рассылку "PHP 5 для начинающих".

PHP 5: Новые возможности.

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

  1. Создание необходимой структуры директорий.

  2. Перенаправление запросов в файл начальной загрузки.

  3. Создание файла начальной загрузки с главным контроллером.

  4. Создание специализированных контроллеров.

В традиционном веб приложении отдельные страницы собраны в произвольной структуре директорий; при обращении к этим страницам в адресной строке зачастую передаются многочисленные параметры, что делает адрес громоздким, затрудняет его визуальное восприятие и, тем более, ручной набор (Пример 4.1, «Пример запроса в традиционном стиле»).


Zend Framework предлагает принципиально иной подход к организации веб приложения. Практически все скрипты выносятся за пределы веб сайта (обычно в директорию, расположенную на один уровень выше корневой директории сайта). В корневой директории остается единственный скрипт - index.php, обеспечивающий начальную загрузку приложения.

[Подсказка]Подсказка

Путь к корневой директории веб сайта содержится в значении переменной $_SERVER['DOCUMENT_ROOT'].

Запрашиваемые URI уже не адресуются к реальным страницам на сайте, а содержат определенную информацию, управляющую работой приложения; все такие запросы перенаправляются в файл начальной загрузки. Находящийся в этом файле главный контроллер анализирует каждый запрос и, в зависимости от содержащейся в нем информации, передает его другому, более специализированному контроллеру. Этот процесс называется роутингом и далее будет рассмотрен более подробно («Роутинг»).

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

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


Рекомендуется использовать во всех приложениях на основе Zend Framework стандартную структуру директорий и файлов [9]. Это, по меньшей мере, облегчит понимание кода другими разработчиками, знакомыми с Zend Framework.

Предлагаемая структура (Пример 4.3, «Рекомендуемая структура директорий») включает в себя библиотеку классов Zend Framework, библиотеку классов самого приложения, а также файл начальной загрузки - главный контроллер (index.php), конфигурационный файл веб сервера (.htaccess) и директории с изображениями и страницами стилей.

Предполагается, что библиотека классов Zend Framework уже установлена в недоступном через веб сервер месте (см. «Установка»). Библиотеку классов приложения (их нам еще предстоит разработать) рекомендуется установить там же.

Дерево директорий библиотеки классов приложения должно отражать использование им MVC шаблона, т. е. включать в себя отдельные директории для контроллеров, видов и модели данных.

Остальные перечисленные компоненты предлагаемой структуры находятся в корневой директории веб сайта.


[Замечание]Замечание

Безусловно, в реальном приложении рекомендуемая структура может быть несколько изменена (например, в корневую директорию может быть добавлена директория с Javascript файлами, а уровнем выше - директория с библиотекой классов PEAR), но общий дух предложения должен быть сохранен.

Перенаправление запросов к серверу производится с целью концентрации их в одном-единственном файле начальной загрузки (index.php в корневой директории сайта). Содержащийся в этом файле главный контроллер будет обеспечивать последующую обработку этих запросов. Запрашиваемые адреса страниц (URI) должны быть ясными, без дополнительных параметров (query) или с минимальным их количеством.

Для перенаправления воспользуемся директивами модуля mod_rewrite (см. «Требования к серверу»), включив их в конфигурационный файл веб сервера .htaccess в корневой директории сайта. Однако, сначала определим общую стратегию такого перенаправления.

Предпочтительнее перенаправлять запросы по принципу «все, кроме...» (Пример 4.4, «Перенаправление с исключением отдельных типов файлов», Пример 4.5, «Перенаправление с исключением отдельных директорий»), т. е. указывать признаки только тех запросов, которые не будут перенаправлены - например, в большинстве случаев вряд ли целесообразно использовать Zend Framework для передачи в броузер изображений и страниц стилей.

[Подсказка]Подсказка

На этапе разработки, пока еще не вполне ясна окончательная структура директорий приложения, удобнее исключать файлы с определенными расширениями (Пример 4.4, «Перенаправление с исключением отдельных типов файлов»). В готовом приложении правильнее исключать целые директории (Пример 4.5, «Перенаправление с исключением отдельных директорий»).

Пример 4.4. Перенаправление с исключением отдельных типов файлов

RewriteEngine On
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php 1
            
1

Запросы к файлам с расширениями .js, .ico, .gif, .jpg, .png и .css не будут перенаправлены; все остальные запросы будут перенаправлены в файл index.php.


Пример 4.5. Перенаправление с исключением отдельных директорий

RewriteEngine On
RewriteRule !^(js|images|styles) index.php 1
            
1

Запросы к файлам в директориях js, images и styles не будут перенаправлены; все остальные запросы будут перенаправлены в файл index.php.


Однако, если приложение разрабатывается на сайте с уже существующим самостоятельным контентом, то придется применить другую стратегию - указывать, какие директории следует перенаправлять Пример 4.6, «Альтернативный способ перенаправления».

Пример 4.6. Альтернативный способ перенаправления

RewriteEngine On
RewriteRule ^(news|forum|download|help) index.php 1
            
1

Будут перенаправлены только запросы к файлам в директориях news, forum, download и help.


Далее займемся файлом index.php в корневой директории веб сайта, обеспечивающим начальную загрузку приложения. Именно сюда будут стекаться все перенаправленные запросы. Для их обработки разместим в этом файле главный контроллер - класс Zend_Controller_Front - и статически вызовем его метод run, указав в качестве параметра путь к специализированным контроллерам.

Zend_Controller_Front::run(ZF_CONTROLLERS);

Для успешной работы этой строке кода необходимы несколько подготовительных действий (Пример 4.7, «Файл начальной загрузки»), но именно она является центральной в будущем приложении, так как обеспечивает его базовую функциональность. В дальнейшем мы будем только наращивать эту функциональность, добавляя специализированные контроллеры и виды.

Пример 4.7. Файл начальной загрузки

<?php

define('ZF_ROOT', realpath($_SERVER['DOCUMENT_ROOT'].'/../')); 1
define('ZF_CONTROLLERS', ZF_ROOT.'/application/controllers'); 2

set_include_path(get_include_path().PATH_SEPARATOR.ZF_ROOT.'/library'); 3

require_once 'Zend/Controller/Front.php'; 4

Zend_Controller_Front::run(ZF_CONTROLLERS); 5

?>
            
1

Определение пути к директории, в которой расположена библиотеки классов Zend Framework и самого приложения. Вместо жесткого задания пути к директории он вычисляется «на лету» относительно корневой директории сайта. Это упрощает перенос приложения с одного сервера на другой, например, с локального на удаленный.

2

Задание пути к специализированным контроллерам.

3

Настройка пути для поиска включаемых файлов при помощи добавления директории с библиотекой классов Zend Framework. Использование стандартной константы PATH_SEPARATOR способствует платформенной независимости приложения.

4

Включение файла с классом Zend_Controller_Front, который будет использован в качестве главного контроллера.

5

Запуск главного контроллера.


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

Каждому токену - части запрошенного адреса, которая отделена от других слэшем (косой чертой), присуще определенное значение.

http://www.example.com/<controller>/<action>/

Первые два токена - протокол и название хоста - игнорируются, а вот следующие два трактуются как название специализированного контроллера, которому должно быть передано управление, и название действия, которое этот контроллер должен выполнить. Если один или оба эти токена отсутствуют, то контроллер и/или действие принимают значение по умолчанию - index.

Кроме того, запрос может содержать произвольное количество дополнительных параметров, представленных в виде пары «ключ/значение».

http://www.example.com/<controller>/<action>/<key1>/<value1>/<key2>/<value2>/

Теперь рассмотрим, как будет обработан, например, следующий запрос.

http://www.example.com/foo/bar/

Главный контроллер, получив этот запрос, передаст управление специализированному контроллеру, представленному классом FooController, находящемуся в файле FooController.php в директории ZF_CONTROLLERS[3]; при этом будет вызван метод barAction, принадлежащий этому классу.

[Подсказка]Подсказка

Обратите внимание на то, что в адресе название контроллера начинается со строчной буквы, а название соответствующего класса (и файла, в котором он содержится) - с заглавной. Кроме того, к запрошенным названиям контроллера и действия добавляются соответственно слова Controller и Action. Таким образом, токену foo в запросе соответствует класс FooController (и файл FooController.php), а токену bar - метод barAction.

Существует несколько постулатов, верных по отношению ко всем приложениям, разработанным на основе Zend Framework.

  1. Специализированные контроллеры являются наследниками класса Zend_Controller_Action, входящего в состав поставки Zend_Framework.

  2. Каждый контроллер обслуживает определенную смысловую зону на веб сайте.

    [Подсказка]Подсказка

    В некотором смысле, контроллеры соответствуют директориям в традиционном веб приложении.

  3. В каждом контроллере обязательно должен быть определен метод indexAction для обслуживания действия по умолчанию, если оно не задано явным образом в запросе.

    [Подсказка]Подсказка

    По сути, метод indexAction соответствует индексной странице (index.php, index.html и т. п.) в традиционном веб приложении.

  4. В состав каждого приложения обязательно должен входить класс IndexController для обслуживания запросов, в которых контроллер не задан явным образом (Пример 4.8, «Класс IndexController»).

    [Подсказка]Подсказка

    Контроллер IndexController соответствует корневой директории вебсайта в традиционном веб приложении, а его метод indexAction - домашней странице веб сайта.

Пример 4.8. Класс IndexController

<?php

require_once 'Zend/Controller/Action.php';

class IndexController extends Zend_Controller_Action {
    public function indexAction()
    {
        // HOME PAGE
        print 'Sorry, we are still under condtruction.'; 1
    }

    public function noRouteAction()
    {
        $this->_redirect('/'); 2
    }
}

?>
            
1

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

2

Перенаправление на домашнюю страницу.


[Замечание]Замечание

Обычно методы контроллеров создают экземпляр класса Zend_View, входящий в поставку Zend Framework, передают ему необходимые данные и вызывают метод render, который исполняет соответствующий скрипт, обеспечивающий отображение этих данных. Однако, в силу дополнительной сложности, этот механизм будет рассмотрен в основном курсе.

  1. Создайте отсутствующие директории, руководствуясь рассмотренной ранее структурой (см. Пример 4.3, «Рекомендуемая структура директорий»).

  2. Внесите следующие изменения в конфигурационный файл веб сервера .htaccess в корневой директории веб сайта.

    RewriteEngine On
    RewriteRule ^quickstart index.php
                    
  3. Создайте файл начальной загрузки index.php в корневой директории сайта (см. Пример 4.7, «Файл начальной загрузки»).

    [Подсказка]Подсказка

    Если структура директорий для библиотеки классов приложения соответствует рекомендованной (Пример 4.3, «Рекомендуемая структура директорий»), то просто вставьте код из примера в созданный файл; в противном случае внесите в названия директорий соответствующие изменения.

  4. Создайте в директории application/controllers файл IndexController.php и вставьте в него соответствующий код (см. Пример 4.8, «Класс IndexController»).

  5. Загрузите домашнюю страницу сайта (укажите только протокол и название хоста, например: http://www.example.com/, указав, конечно, вместо www.example.com реальное название хоста). Если все работает правильно, то Вы увидите следующее сообщение.

    Sorry, we are still under condtruction.
  6. Создайте в директории application/controllers файл QuickstartController.php и вставьте в него следующий код.

    <?php
    
    require_once 'Zend/Controller/Action.php';
    
    class QuickstartController extends Zend_Controller_Action {
        public function indexAction()
        {
            print 'Congratulations! It was really quick start!';
        }
    }
    
    ?>
                    
  7. Загрузите адрес http://www.example.com/quickstart/, указав, конечно, вместо www.example.com реальное название хоста. Вы должны увидеть следующее сообщение.

    Congratulations! It was really quick start!

    Работающий демонстрационный пример находится здесь.

  8. Попытайтесь загрузить адрес, который содержал бы непредусмотренное (нереализованное в приложении) название контроллера и/или метода, например, http://www.example.com/quickstart/error/. Вы увидите (на экране или в лог файле) длинное сообщение о неперехваченной исключительной ситуации.

    PHP Fatal error:  Uncaught exception 'Zend_Controller_Action_Exception'
    with message 'QuickstartController::errorAction() does not exist and was
    not trapped in __call().' [...skipped...]
                    

    Предложите простое решение, предотвращающее появление подобных сообщений.

  9. Предложите способ оптимизации приложения, позволяющий отказаться от постоянного использования выражения require_once.

  10. Внесите оба усовершенствования в свое приложение (не забудьте удалить ставшие ненужными выражения require_once).

«Ответы и решения к Глава 4, Быстрый старт»

[Подсказка]Подсказка

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

Created with DocBook


В избранное