Автор: Митрошин Сергей

Доброго времени суток всем. Сейчас я расскажу вам о том, что такое Zend Framework, зачем он нужен и как его использовать. Эта статья не раскроет вам всех тонкостей Zend Framework. Также она не заменит такие замечательные вещи, как документацию и API.
Благодаря этой статье вы сможете определить, подходит вам Zend Framework, или вас более заинтересуют его аналоги (Symfony, CakePHP, CodeIgniter). Также вы получите информацию, необходимую для начала его использования и работы с ним.

Часть 0. Введение.

Zend Framework – фреймворк для PHP. Если быть более точным – это CMF, что, как считает Википедия, “инструментарий для создания систем управления содержимым, а также веб-приложений”. Иными словами, фреймворк – это каркас для написания программы.
В свою очередь, Zend Framework – один из лучших PHP-фреймворков, позволяет нам экономить силы и предоставляет поистине огромные возможности для написания сайтов и веб-приложений.
Сейчас я перечислю основные компоненты этого фреймворка, и возможности, которыми они обаладают.

  • Zend_Acl – управление разграничением прав доступа групп пользователей
  • Zend_Auth – аутентификация пользователей
  • Zend_Cache – управление кешированием
  • Zend_Config – предоставляет возможности для удобного доступа к данным из конфигурационных ini и xml файлов
  • Zend_Controller – основной класс фреймворка, реализующий паттерн MVC
  • Zend_Date – много удобных возможностей для работы с датой
  • Zend_Db – работа с базами данных
  • Zend_Feed – работа с лентами RSS и Atom
  • Zend_Filter – предназначен для фильтрации входных данных
  • Zend_Gdata – интеграция с сервисами Google (Docs, App, Calendar, YouTube и др.)
  • Zend_Log – автоматизация записи в логи
  • Zend_Mail – отправка e-mail
  • Zend_Service – интеграция с интернет-сервисами (Amazon, Del.icio.us, Flickr, Yahoo и др.)
  • Zend_Session – работа с сессиями
  • Zend_View – шаблонизатор, компонент MVC

Ещё один момент. Zend Framework не принесёт вам значительной пользы при создании на его основе сайтов-визиток и подобных им сайтов. В таком случае вам понадобится CMS. Но если вам больше по вкусу серьёзные проекты, то добро пожаловать в мир Zend Framework!
На этом закончим введение. Пора уже программировать :)

Часть 1. Установка Zend Framework

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
lib/
    application/
        controllers/
            IndexController.php
        models/
        views/
            scripts/
                index/
                    index.phtml
            helpers/
            filtres/
    config/
    library/
    temp/
public_html/
    .htaccess
    index.php

Теперь подробнее про каталоги.
Как вы видите, у нас есть 2 основных каталога: lib и public_html.
В каталоге lib мы будем хранить почти все наши скрипты. Исключение составит лишь index.php.
Подробнее про содержимое каталога lib:

  • application – хранит в себе наши скрипты контроллеров, моделей и вида (если вы ещё не ознакомились с основными принципами MVC, то сейчас самое время)
  • config – как и следует из названия, файлы конфигурации
  • library – именно туда мы поместим Zend Framework (про это подробнее позже), библиотеки и т.д.
  • temp – как вы уже, наверное, догадались, содержит в себе временные файлы

Каталог public_html – основной публичный каталог. У разных хостеров он может называется по-разному: www, htdocs и т.д. Но суть у них одна и та же.

Как вы видите, в каталоге public_html распологаются всего два файла: .htaccess и index.php
.htaccess должен содержать следующие строки:

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

Таким образом мы активируем механизм преобразования ссылок (mod_rewrite) и задаём правило преобразования.
Правило преобразования используется следующее – передавать все запросы файлу index.php. Исключение составляют запросы к файлам с расширениями js, ico, gif, jpg, png, css.

Теперь вам предстоит скопировать сам Zend Framework в каталог lib/library. Сейчас надо уточнить, что скопировать надо папку Zend (в архиве поставки Zend Framework он обычно расположен в каталоге library).

И последнее – содержимое index.php.

1
2
3
4
5
6
7
8
9
10
11
//начальное объявление констант
//позволяет добиться гибкости именования и размещения основных каталогов
define('ROOTPATH', $_SERVER['DOCUMENT_ROOT'] . '/..');
define('HOMEPATH', ROOTPATH . '/public_html');
define('LIBPATH', ROOTPATH . '/lib');      

//устанавливаем каталог библиотек корневым
set_include_path(LIBPATH . '/library');      

require_once('Zend/Controller/Front.php');
Zend_Controller_Front::run(LIBPATH . '/application/controllers');

Часть 2. Контроллеры и действия

Пришло время рассказать о контроллерах (controllers) и действиях (actions).
Скрипт контроллера обычно объединяет в себе несколько действий. Выглядит это так:

1
2
3
4
5
6
7
8
9
10
class ProfileController extends Zend_Controller_Action
{
    public function indexAction() {
        echo 'Hello! I\'m ProfileController, indexAction';
    }      

    public function showAction() {
        echo '
Hello! I\'m ProfileController, showAction';
    }
}

В данном примере indexAction выполнится тогда, когда URL будет таким: “http://sitename.ru/profile”. В свою очередь, showAction выполнится при переходе к URL “http://sitename.ru/profile/show”. Таким образом, шаблон выполнения контроллеров соответствует http://sitename.ru/имя_контроллера/имя_действия
Однако у этого правила существуют исключения. Дело в контроллерах и действиях, используемых по умолчанию. Как вы видите, в URL “http://sitename.ru/profile” не указан action_name. В таких случаях используется имя “index”. Аналогично с ситуацией, когда не указан даже контроллер: “http://sitename.ru”. В таком случае будет выполнен IndexController, indexAction.
Располагаются контроллеры в каталоге lib/application/controllers. Для каждого контроллера – свой файл с именем, соответствующим имени класса (например, ProfileController.php).
Расскажу немного о правилах именования действий и контроллеров. Имя контроллера всегда начинается с заглавной буквы – IndexController, ProfileController. А имя действия, напротив, содержит лишь буквы нижнего регистра.

Вот и всё. Теперь вы знаете основы. В следующей статье я расскажу вам про Zend_Controller подробнее. Также мы ознакомимся с Zend_View.
До свидания.

27 Comments

  1. Roman says:

    Ставлю Zend Framework но постоянно вылетает ошибка при загрузке фала настроек для БД

    Warning: parse_ini_file(c://www/rasprodagafront/application/config.ini) [function.parse-ini-file]: failed to open stream: No such file or directory in C:\www\rasprodagafront\library\Zend\Config\Ini.php on line 106

    Fatal error: Uncaught exception ‘Zend_Config_Exception’ with message ‘Section ‘general’ cannot be found in c://www/rasprodagafront/application/config.ini’ in C:\www\rasprodagafront\library\Zend\Config\Ini.php:156 Stack trace: #0 C:\www\rasprodagafront\public\index.php(15): Zend_Config_Ini->__construct(‘c://www/rasprod…’, ‘general’) #1 {main} thrown in C:\www\rasprodagafront\library\Zend\Config\Ini.php on line 156

    уже не знаю что и делать все перепробовал, ini файл этот лежит там где и положено.

  2. admin says:

    Судя по тексту исключения, вы забыли указать имя секции при инстанцировании класса Zend_Config_Ini и оно подставило значение ‘general’. Такой секции у вас нет, и ZF выбрасывает исключение.
    Попробуйте отследить ошибку, исходя из этого.
    Если не поможет, то покажите мне:
    - содержимое ini-файла (пароли предварительно уберите :) )
    - код, которым вы подключаете ini-файл

  3. Roman says:

    сам ini

    [general]
    db.adapter = PDO_MYSQL
    db.config.host = localhost
    db.config.username = root
    db.config.password = 1
    db.config.dbname = test

    index.php где и идет вызов ini
    throwExceptions(true);
    $frontController->setControllerDirectory(‘./application/controllers’);

    // load configuration
    $config = new Zend_Config_Ini(‘../application/config.ini’, ‘general’);
    $registry = Zend_Registry::getInstance();
    $registry->set(‘config’, $config);

    // run!
    $frontController->dispatch();

    еще временами вылетает вот это

    Uncaught exception ‘Zend_Controller_Dispatcher_Exception’ with message ‘Invalid controller specified (index)’ in C:\www\rasprodagafront\library\Zend\Controller\Dispatcher\Standard.php:249 Stack trace: #0 C:\www\rasprodagafront\library\Zend\Controller\Front.php(914): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http)) #1 C:\www\rasprodagafront\public\index.php(25): Zend_Controller_Front->dispatch() #2 {main} thrown in C:\www\rasprodagafront\library\Zend\Controller\Dispatcher\Standard.php on line 249

    такое ощущение что то не то с путями но вот что не могу понять.

  4. admin says:

    Попробуйте прописать абсолютные пути к ControllerDirectory и ini-файлу.

    А зачем вы положили config.ini в каталоге application? Лучше создайте каталог config, в нём и держите файлы конфигурации, а не сваливайте всё в одну кучу.

  5. Roman says:

    абсолютный путь помогает, но из за путей, глюк вылезает дальше такой же самый но уже связанный с другим файлом,
    Warning: Zend_Loader::include_once(Companies.php) [function.Zend-Loader-include-once]: failed to open stream: No such file or directory in C:\www\front\library\Zend\Loader.php on line 83

    Warning: Zend_Loader::include_once() [function.include]: Failed opening ‘Companies.php’ for inclusion (include_path=’C:/www/front/public/../library’) in C:\www\front\library\Zend\Loader.php on line 83

    я же везде не могу прописать абсолютные пути, вот полный index.php, попробовал с абсолютными через DOCUMENT_ROOT работать, не помогает

    throwExceptions(true);
    $frontController->setControllerDirectory(‘c://www/front/application/controllers’);

    // load configuration
    $config = new Zend_Config_Ini(‘../application/config.ini’, ‘general’);
    $registry = Zend_Registry::getInstance();
    $registry->set(‘config’, $config);

    // setup database
    $db = Zend_Db::factory($config->db->adapter,
    $config->db->config->toArray());
    Zend_Db_Table::setDefaultAdapter($db);

    // run!
    $frontController->dispatch();

  6. Roman says:

    что то wordpress заглючивает на throwExceptions и все что выше не показывается

  7. Roman says:

    error_reporting(E_ALL|E_STRICT);
    $a=’.’.PATH_SEPARATOR .$_SERVER['DOCUMENT_ROOT'].’/library’
    .PATH_SEPARATOR.$_SERVER['DOCUMENT_ROOT'].’/application/models/’
    .PATH_SEPARATOR.get_include_path();
    set_include_path($a);

  8. admin says:

    Что-то ты вообще с путями запутал. Да ещё и вордпресс обрезает половину кода.
    Укажи везде абсолютные пути. Сейчас я вижу, что путь к ини-файлу относительный. Могут возникать проблемы из-за этого.
    Больше ничего из своего положения сказать не могу.

  9. Roman says:

    ini я пробовал по разному, с абсолютным работает, но внутри классов зенда я не могу изменить путь на абсолютный т.к. он там вызывает файл, и считает что он есть в include_path, но его там нет, вот например вызов из БД и его ошибка.

    models/Companies.php

    <?php

    class Companies extends Zend_Db_Table
    {
    protected $_name = ‘companies’;
    }

    Warning: Zend_Loader::include_once(Companies.php) [function.Zend-Loader-include-once]: failed to open stream: No such file or directory in C:\www\rasprodagafront\library\Zend\Loader.php on line 83

  10. admin says:

    Что тебе мешает использовать абсолютные пути везде, где инклуды твои, а не ZF?
    Прописываешь include_path к каталогу ZF, а сам в index.php объявляешь константы с путями, и используешь их во всех своих инклудах.
    Например, как здесь

  11. Виктор says:

    Спасибо было полезно, узнал много нового

  12. Роман says:

    Не пойму, почему когда ввожу http://sitename/show не вызывается контроллер по умолчанию и действие show. Контроллер по умолчанию может вызывать разные действия?

  13. admin says:

    Роман, при вызове http://sitename/show вызывается ShowController, indexAction. Чтобы вызвать действие slow контроллера по умолчанию необходимо использовать УРЛ http://sitename/index/show

  14. Роман says:

    Спасибо. У меня все равно проблемка.

    в файле index.php:

    set_include_path(‘../lib/library’);
    require_once(‘Zend/Controller/Front.php’);
    $obj=Zend_Controller_Front::getInstance();
    $front->setControllerDirectory(‘../lib/application/controllers’);
    $front->dispatch();

    а в файле IndexController.php:

    class IndexController extends Zend_Controller_Action

    {

    public function indexAction() {
    echo ‘Hello! I\’m IndexController, indexAction’;
    }

    public function showAction() {
    echo ‘Hello! I\’m ShowController, showAction’;
    }

    }

    В таком случае по адресу http://localhost/ запускается действие по умолчанию, а по адресу http://localhost/index/show выскакивает ошибка 404.

    Я наверное что-то упустил…

  15. admin says:

    Очевидно, вы забыли включить mod_rewrite. Для этого в каталоге с index.php вам необходимо создать файл .htaccess и указать в нём правила редиректа. Лично я предпочитаю следующее правило:

    RewriteEngine on
    RewriteRule ^[^\.]+$ index.php

    Все URLы без точки будут переадресовываться на index.php и работать через ZF. А URLы с точкой (style.css, function.js и т.д.) – будут вызваться напрямую.

  16. Роман says:

    Файл .htaccess я тоже создал с правилами.
    Но вы навели меня на мою глупую ошибку, у меня вообще не загружался модуль, исправил в httpd.conf. Да еще к тому же директива AllowOverride имела значение None. Все понятно.

    Правда выскакивает ‘Invalid controller specified (error)’ теперь при запросе index/show. Думаю нужно как-то править контроллер.
    Есть класс IndexController , в котором есть действие show, я думал оно и должно вызываться, но потом обратил внимание что оно должно выводить ‘Hello! I\’m ShowController, showAction’; Причем здесь ShowController…

    Видимо я что-то упускаю, почитаю еще очень внимательно статьи. Спасибо за помощь!!

  17. admin says:

    Не за что )

    ‘Invalid controller specified (error)’ выбрасывается у вас скорее всего из-за того, что не отключен viewHelper, автоматически обрабатывающий скрипты вида, а скрипты вида у вас не созданы. ZF передаёт управление ErrorController::errorAction(), а он тоже не существует.

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

  18. Пингвин says:

    я не согласшусь, не правильно вы говорите

  19. armjer says:

    Здравствуйте. Прочел Вашу статью с большим интересом.
    Я пытаюсь установить Zend Framework. Сделал как у Вас написано, но у меня не получается. Появляется ошибка.

    КОД.
    throwExceptions(true);
    try {
    $frontController->dispatch();
    }
    catch (Exception $e)
    {
    echo “myerror:{$e->getMessage()}”;
    }
    //$frontController->dispatch();
    echo(“Test”);
    ?>
    КОД.
    Ошибка.
    myerror:No default module defined for this application

    Я прошу, если не трудно для Вас, помочь мне.

  20. Сергей Митрошин says:

    Судя по всему, вы используете модули, и модуля default у вас не существует.

  21. Raindi says:

    Прошу помочь выдает ошибку

    Fatal error: Uncaught exception ‘Zend_Log_Exception’ with message ‘”/var/www/phpweb20/data/logs/debug.log” cannot be opened with mode “a”‘ in C:\XAMPP\xampp\php\PEAR\Zend\Log\Writer\Stream.php:69 Stack trace: #0 C:\XAMPP\xampp\htdocs\Practical_Web_2_0_Applications_with_PHP-3904\chapter-02\htdocs\index.php(11): Zend_Log_Writer_Stream->__construct(‘/var/www/phpweb…’) #1 {main} thrown in C:\XAMPP\xampp\php\PEAR\Zend\Log\Writer\Stream.php on line 69

  22. Alexander says:

    В “части 0. Введение” в самом конце опечутка =) “Пока уже программировать” – на – “ПоРа уже программировать “

  23. Сергей Митрошин says:

    Alexander спасибо, поправил

  24. Anton says:

    Скажите пожалуйста в чем беда …
    Пытаюсь запустить на сервере IIS URL rewrite вроде выставил
    но страница открывается с 500 ошибкой в файле php-errors.log пишет такие ошибки …

    [11-May-2011 17:06:38] PHP Fatal error: Uncaught exception ‘Zend_Controller_Dispatcher_Exception’ with message ‘Invalid controller specified (error)’ in C:\inetpub\wwwroot\library\Zend\Controller\Dispatcher\Standard.php:248
    Stack trace:
    #0 C:\inetpub\wwwroot\library\Zend\Controller\Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
    #1 C:\inetpub\wwwroot\public\index.php(30): Zend_Controller_Front->dispatch()
    #2 {main}
    thrown in C:\inetpub\wwwroot\library\Zend\Controller\Dispatcher\Standard.php on line 248

    Вроде похоже на то, что было у Romana

  25. Сергей Митрошин says:

    Антон, вам надо включить параметр throwExceptions и посмотреть, что его вызывает.
    Сейчас же ZF пытается вызвать обработчик ошибок (ErrorController, errorAction), но не находит его.

  26. Anton says:

    А не могли бы вы подсказать где его искать …:(

  27. Сергей Митрошин says:

    Можно включить его в application.ini:
    resources.frontController.throwExceptions = 1

Leave a Reply