Zend Framework 1.0.0 – как бы я строил начальный каркас

Не знаю, на сколько я прав в этом вопросе, но я не думаю, что совершил много грубых ошибок в проектировании. Тех, кто далёк от архитектуры Model-View-Controller попрошу остановиться и ознакомиться где-либо с этой идеологией.

Итак, для установки Zend Framework 1.0.0 на сервер не нужно никаких особых шаманств с бубном. Всё что вам нужно, это соответствовать требованиям Zend Framework. Там нет ничего сложного – PHP 5.1.4 (рекомендуется 5.2.2), SPL и, возможно, некоторые extensions, если вы будете использовать определённые компоненты Zend Framework.

Структура каталогов для быстрого старта с Zend Framework о которой пойдёт речь далее.

Для простоты, что-бы не вдаваться в особенности разных конфигураций серверов, предлагаю файлы Zend Framework положить в каталог library либо сразу в корневой каталог сервера (я имею ввиду Document Root). В случае использования каталога library, нам придётся изменить include_path для данного проекта, что можно сделать в .htaccess или в httpd.conf (php_value include_path “.;D:/devserv/www/zfstart/www/library/”), либо при помощи php.ini (include_path = “.;D:/devserv/www/zfstart/www/library/”). Всё, конечно, зависит от програмного обеспечения и конфигурации сервера, который вы используете. Проще говоря, каталог Zend с его содержимым должен находиться в досегаемости для PHP, описанной в include_path.

Согласно Zend Framework manual структура каталогов должна быть следующей:

application/
    controllers/
        IndexController.php
    models/
    views/
        scripts/
            index/
                index.phtml
        helpers/
        filters/
html/
    .htaccess
    index.php

Однако, изза разницы конфигурации разных серверов и способов доступа, данная конфигурация может быть не всегда доступна. Учитывая весь скопленный мною опыт работы на литовких, китайских и американских серверах, что либо складывать вне Document Root часто неудаётся (Дело в том, что многие маленькие и средние проекты используют дешёвый хостинг, где вечно всё не так, но никто ничего уже не изменит). Поэтому я осмелюсь предложить свою структуру (в неё сразу включён обработчик ошибок).

www/
    application/
        controllers/
            ErrorController.php
            IndexController.php
        models/
        views/
            scripts/
                error/
                    error.phtml
                index/
                    index.phtml
            helpers/
            filters/
        .htaccess
    config/
        config.xml
        .htaccess
    library/
        Zend/
        .htaccess
    .htaccess
    index.php

Что позволяет хранить все файлы внутри Document Root, защищая нужные файлы от внешнего доступа при помощи .htaccess файлов. Для детального рассмотрения структуры и кода, о котором пойдёт разговор дальше, предлагаю скачать ZIP-файл с выше описанной структурой файлов (если вы этого не сделали раньше).

Хочу заметить, что мною рассматривается ситуация, когда PHP установлен как mod_php на Apache 2.0.x, включен mod_rewrite и у меня есть право использовать директиву Order. Да, да, я знаю, структура ужасно похожа на Ruby on Rails в котором мне очень не нравилось, что каталог public не там где мне хотелось и нужно было шаманить то по SSH, не то администраторов пинать.

Корневой .htaccess предельно прост – несколько настроек PHP, директивы mod_rewrite и ErrorDocument (что не мало важно для красивой обработки 403 ошибки). Остальные все как один:

Order Deny,Allow
Deny from All

Из Zend Framework manual можно легко выудить информацию о том, как быстро запустить первый шаг (правда её нужно собирать по крупицам с разных страниц). Какие классы нам нужны и когда их подгружать. На иллюстрации можно увидеть, как и в каком порядке я подгружаю классы для старта.

Это файл вы найдёте в ZIP-файле быстрого старта.

А ведь ничего особенного: Zend_Controller_Router_Rewrite, Zend_Controller_Router_Route, Zend_Controller_Front, Zend_Controller_Action, Zend_Config_Xml, Zend_Registry, Zend_Db и Zend_Db_Table_Abstract – это всё что потребуется для начала.
Далее последует инициализация конфига, его передача в регистры (там-же потом Zend_Db поместить соединение с базой, которое будет использоваться по умолчанию, что-то вроде глобальной переменной через статичные методы и singelton), подключение к базе, инициализация и настройки контроллера (Controller).

Попрошу обратить внимание на 40 строку этого файла – $frontController->throwExceptions(true); – вызов данного метода со значением параметра true означает, что все произошедшие ошибки будут вывалены в броузер, стоит его сменить на false как вместо ошибок будет показана 404 ошибка (ErrorController::errorAction). Пока я с этим разобрался – потратил не один десяток минут.

По умолчанию обработчик ошибок в Zend Framework это контроллер с названием ErrorController, в котором должен быть метод errorAction, а для него должен быть view-файл error.phtml (все эти файлы мною уже включены в поставку, и как только вы измените значение throwExceptions на false всё заработает). Лично я считаю, это очень удачный подход. У многих начинающих коллег на Ruby on Rails очень часто встречаются (скорее нечаянно) страницы где вываливаются дампы ошибок, что весьма и весьма неприятно (индексация поисковиками, вопросы безопастности).

Коротко о Zend_Controller_Action (точнее его наследниках). Какой Контроллер (Controller) и его Mетод (Action) будет использован, подбирается согласно правилам Routing (кстати, их есть 3 типа: Zend_Controller_Router_Route_Static, Zend_Controller_Router_Route_Regex и Zend_Controller_Router_Route). Все контроллеры называются по типу: <Название>Controller, а их методы <Название>Action.

Каждый контроллер имеет свой каталог для view-файлов, названный как контроллер. К примеру, для контроллера IndexController создаётся каталог index (каталог application/views/scripts/). Каждый Mетод контроллера имеет свой файл-шаблон, названный как этот метод. К примеру для indexAction создаётся файл index.phtml. Как вы уже поняли из расширения файла, шаблонный движок по умолчанию – PHP, но, уже сейчас можно порадовать любителей Smarty – его поддержка уже есть.

Хочу заметить, что я намеренно пока обошёл работу с базой, но сразу предупрежу – модели (из каталога application/models/) сами не грузятся. С кем не говорил из знакомых – все грузят руками через include/require, кто в index.php на старте всё сразу, кто в контроллера по нужде. Хотя, замечу что здесь вообще, понятие модели нет, так как Zend имплементировал немножко другую идеологию, нежели ActiveRecord в Ruby on Rails. Сам я до конца в принципах работы ещё не разобрался и вам пока ничего про это писать не буду.

Думаю данного примера достаточно, что-бы сделать первый шаг в изучении Zend Framework. Именно такого примера мне не хватало, когда я начал изучать Zend Framework. Часть кода, использованнго в примере взята с сайта Zend Framework – так оно быстрее и проще, как для меня, так и для читающих.

20 thoughts on “Zend Framework 1.0.0 – как бы я строил начальный каркас

  1. Чтобы грузились модели, нужно добавить их в include_path.
    Типа вот так

    set_include_path(‘.’ . PATH_SEPARATOR . ‘../library/’
    . PATH_SEPARATOR . ‘../application/default/models’
    . PATH_SEPARATOR . get_include_path() );

  2. Ещё один способ, да :)

    Интересное, что у уже их 2.
    1) просто все модели загрузить через ZendLoader::loadClass добавив туда путь до каталога моделей, сразу после соединения к базе (как это сделано в Ruby on Rails)
    2) изменить include_path и подгружать их прямо в контроллерах как говорите вы.

  3. Очень занимательная статейка….
    Вот сижу над Zend Framework…. голова пухнет ….
    Документация оч. не вполне понятная, в связи с этим изучение может затянутся. Может посоветуете с чего начать(т.е. продолжить изучение)?

  4. Я думаю с документации. Я с неё начинал. Можете ещё статьи на английском поискать – тоже полезно.

  5. Спасибо за интересный материал, все проблемы с которыми я столкнулся тут описанны :)

    По поводу смарти хотелось бы спросить. В ZF есть его поддрежка?
    Мне пока приходиться делать вот так:

    $frontController->setParam(‘noViewRenderer’, true);

    Потом регистрировать смарти:
    $smarty = new Smarty();
    .
    .
    .
    .
    Zend_Registry::set(‘smarty’, $smarty);

    И в экшенах пишу:
    $registry = Zend_Registry::getInstance();
    $smarty=$registry->get(‘smarty’);
    и уже можно работать со смарти :)

  6. “модели (из каталога application/models/) сами не грузятся” – я в шоке…

  7. eXDee – это плюс, так ка Zend Framework можно и нужно использовать не толька для работы с базой. И то что у него нет одной постоянной структуры как у Ruby on Rails делает его куда более гибким.

    К примеру – если вы пишите XML-RPC клиент, которому база не нужна и у него одна маленькая задача по выполнении 1-2 операций раз в 2 суток, сложный каркас с кучей проверок “а не надо ли нам ещё чего загрузить из каталога models, helpers и ещё от куда-нибудь” тут совсем не нужен.

  8. Спасибо огромное за статью! Много полезного!

  9. Спасибо за статью.
    1. Но возник вопрос – почему у вас файлы PHP имеют закрывающий тег ?> для <?php ???
    2. Как делать методы в контроллерах без VIEW? Например, мне нужен метод в контроллере который будет просто переходить на другой сайт, а не отображать что-либо.

  10. 1. Хороший вопрос про “почему” – у меня такая привычка – ставить закрывающий тег в PHP скриптах. Я так делаю ещё с 2001 года. И да, строго слежу за тем, чтоб за ним небыло никаких пробелов. Если сделать короткий RTFM то из Note можно понять – это дело вкуса.

    2. Без понятия. Меня сняли с проектов с Zend Frmawork и перевели в комманду поддержки одного старого проекта, где нет никаких Framework, зато нагрузки запредельные.

  11. Респект! Очень полезно! Особенно про обработчик ошибок большое спасибо!

  12. Возник вопрос – только у меня в zf не работают глобальные переменные? Например, я хочу иметь глобальную переменную, хранящую пользовательские права (acl-объект), в bootstrapper’е объявляю и инициализирую переменную как global и пытаюсь в специально отведенном контроллере получить к ней доступ (предварительно указав, конечно, что она global) – получаю undefined variable. Register_globals on ситуации не меняет. Наверное, можно хранить объект в регистре, но просто хотелось бы знать что это за фигня и как с глобальными переменными в zf обращаться.

  13. Вопрос вдогонку: метод get реестра возвращает копию объекта или ссылку на объект? Как модифицировать данные в реестре?

  14. Забудьте global. На крайней случай используйте массив $GLOBALS. Но так вы в любом случае рескуете всё запороть несанкционированным воздействием на любую переменную. Нечаянно возмэте и перезапишите её. Или кто-то перезапишет.

    Пользуйте Zend_Registry. Zend_Registry::get возвращает ссылку на объект. В PHP5 теперь везде ссылки на объекты. И об этом не следует забывать. Полезная ссылка для вас: http://framework.zend.com/manual/ru/zend.registry.html

    У Zend Framework очень многое основано на Zend_Registry.

  15. Ура! При помощи вашей заготовки проекта, у меня наконец-то заработал ZF, до этого час бился с ошибками. :)

    Такой вопрос: почему вы игнорируете рекомендации не ставить в проектах ZF закрывающий тэг PHP?

  16. Потому что мне нравиться закрывать PHP код закрывающим PHP тэгом. За свои 6 лет работы, начиная с PHP 4, я к этому настолько привык, что всё не могу никак отвыкнуть.

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

    Тем более, что личное дело каждого – следовать или не следовать стандартам в своих личных проектах.

    А где-то в сети есть статья, как ускорить работу проекта на ZF, если у вас много трафика, просто убрав все require_once по всему коду. Так что никто и ничто не иделаьно.

  17. Pingback: Фреймворки на PHP | Веб-лог программиста

  18. Спасибо за хороший и простой пример. А то после чтения документации – башка пухнет.

  19. Неплохая статья, для начинающих изучать zf)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.