01. Начало
На протяжении серии статей будет подробно рассмотрена, от начала и до конца, разработка приложения с использованием Zend Framework. То что получилось, доступно по адресу zf-demo.2developers.net. Результатом этой статьи станет так называемый Hello World на Zend'e, в следующих статьях будем наращивать функционал, используя различные компоненты ZF. Если вы никогда не имели дела с ZF, то что бы понять о чем идет речь и нужно ли вам это, попробуйте .Зачем это? Когда я только начал работать с ZF, хотелось посмотреть как это делают другие, услышать какие нибудь советы. Но увы! Находил только бесполезные описания к примерам из мануала, хотя они этого и не требуют. Теперь вот хочу поделиться своими наработками с теми, кто только приходит к пониманию ZF, и как его лучше использовать, а так же подвергнуть критике со стороны опытных разработчиков, имеющих свои предпочтения в работе с ним.
Основные функции приложения:
- посетитель может:
- просматривать статьи и оставлять комментарии;
- просматривать профили пользователей;
- отправлять через контактную форму сообщения на email пользователям;
- регистрироваться;
- пользователи могут:
- добавлять статьи в систему;
- редактировать свои статьи;
- прикреплять файлы;
- редактировать свой профиль;
- а так же:
- Многоязычность;
- Модерация комментариев и постов;
- RSS-лента, как для всего сайта так и отдельные для рубрик;
- основные моменты вынесены в настройки (ini-файлы);
Структура
Что бы было удобнее отлаживаться, рекомендую создать виртуальный хост на локальном сервере, я буду использовать "http://zf-demo.2developers.net".
Примем такую структуру каталогов:

1. app - часто изменяемы файлы, которые относятся непосредственно к приложению.
2. lib - файлы библиотек в т.ч. и нашей, эти файлы как правило редко приходится изменять и использовать более чем в одном приложении.
3. tmp - временные файлы, кэш и логи. После очистки эти дирректорий от файлов приложение продолжает работать без изменений.
4. www - файлы доступные из web'a по http.
- Корневым каталогом сервера при таком расположении, должен быть www (если нет такой возможности заливайте все в корень, только не забудьте далее исправить пути в index.php).
- Каталог lib целесообразнее будет поместить в такое место, где он может быть легко доступен и для других сайтов на вашем сервере.
Загрузчик
Содержимое файла www/.htaccess
RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1
Дальше в index.php добавляем следующий код:
(Краткие пояснения в комментариях, подробности немного позже. Давайте сначала запустим это!)
www/index.php
error_reporting(E_ALL);
// Что бы было легче переезжать или менять структуру каталогов, определим основные пути
define('ROOTPATH', dirname(dirname($_SERVER['SCRIPT_FILENAME'])));
define('LIBPATH', ROOTPATH . '/lib');
define('APPPATH', ROOTPATH . '/app');
define('TMPPATH', ROOTPATH . '/tmp');
define('WWWPATH', ROOTPATH . '/www');
define('HOST', 'http://'.$_SERVER['HTTP_HOST']);
// Если каталог www расположен не в корне сервера указать путь, например - 'zf-demo/'
define('BASEURL', '');
// Добавить в include_path наш каталог lib
$path = implode(PATH_SEPARATOR, array(LIBPATH));
set_include_path($path);
// Что бы сессия была актуальна для всех субдоменов
ini_set('session.cookie_domain', '.zf-demo.2developers.net');
// Засечь время выполнения
global $start_time;
$start_time = microtime(true);
// Инициализируется приложение
require_once('Zend/Controller/Front.php');
$application = Zend_Controller_Front::getInstance();
// Указываем где лежат контроллеры
$application->setControllerDirectory(array(
'default' => APPPATH.'/controllers'
));
// Подключаем ViewRenderer (http://framework.zend.com/manual/ru/zend.controller.actionhelpers.html)
Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
// Файл с маршрутами
require_once(APPPATH.'/Routes.php');
// Вся эта подготовка выполняется примерно за 0.009 сек
/** Выполнение */
$application->dispatch();
/**______________________________________*/
// вычислить и вывести время выполнения
printf ("<!-- <br /> \n Время выполнения: %f sec. -->", microtime(true) - $start_time);
Дополнительная библиотека и базовый контроллер
Следующим шагом будет создание каталога для библиотеки, которую мы будем использовать при необходимости вносить изменения в классы ZF или настраивать с помощью наследования, а так же создавать свои компоненты фрэимворка. Почему не следует изменять файлы, которые находятся в директории lib/Zend, я уверен, вам понятно.
Так что создаем каталог lib/Divo и не станем отклоняться от , и имена классов будут отражаться на именах файлов и директорий.
Теперь напишем класс "базового контроллера", который наследуется от Zend_Controller_Action, и от которого будут наследоваться наши контроллеры действий. Это нужно для того, чтобы иметь возможность добавлять базовые методы, и благодаря наследованию использовать их во всех дочерних контроллерах.
lib/Divo/Controller.php
/** Базовый Класс между Zend_Controller_Action и нашими контроллерами действий.
Содержит базовые методы которые необходимо использовать в более чем одном контроллере */
require_once 'Zend/Controller/Action.php';
class Divo_Controller extends Zend_Controller_Action
{
public function init()
{
// Если каталог www расположен не в корне сервера (см. 11 строка www/index.php)
if (BASEURL !== "") {
$this->getRequest()->setBaseUrl(BASEURL.'/');
}
/** Настройки вида */
// Указываем где искать скрипты вида
$this->view->setScriptPath(APPPATH.'/views/');
$this->divoInit();
}
/** Используется вместо конструктора в дочерних контроллерах */
public function divoInit()
{ }
}
Контроллер действий и скрипт вида
app/controllers/IndexController.php
require_once 'Divo/Controller.php';
class IndexController extends Divo_Controller
{
public function divoInit() //__construct()
{ }
public function indexAction()
{
$this->view->assign("message", "Все работает! Можно перейти к следующей главе");
}
}
и скрипт вида:
app/views/index/index.phtml
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Хелло Ворлд на <?php echo HOST; ?></title>
</head>
<?php echo $this->message; ?>
</html>
Посмотрите результат и следуйте инструкциям.
Приведенный в статье исходный код и структура директорий в приложении, не забудьте добавить в lib каталог с Zend.
Комментарии
Сделал, работает, но можно о струтуре побольше написать, а то неясно что для чего, ведь она не такая как советует Zend
ответ Amigo: Ок. Пока так, просто структура в дальнейшем будет дополняться по мере появления нового функционала, там уже будет расписано более подробно.
Поддерживаю целиком и полностью со структурой приложения, я тоже к этому в свое время пришел.
Вызывать
переопределенный divoInit() наследника в методе init() предка не совсем верно. Правильнее в методе init() наследников вызывать parent::init() предка.Stepan Tanasiychuk, да вы правы, но я просто повторил за разработчиками ZF. Ведь они в конструкторе Zend_Controller_Action посчитали приемлемым вызывать метод init(), вот и я сделал то же самое, только на уровень ниже. Все в духе ZF ;)
я бы перенес папку с моделями (да и другие общие для приложения) из app в lib, чтобы не дублировать файлы в случае использования модулей. А вообще очень полезное начинание, информации по zf для новичков на русском маловато.
Roman, когда у меня на хостинге появилось 2-е и 3-е приложение работающее с библиотекой ZF, её пришлось вынести в корень и тогда полностью стало понятно для чего нужна папка app и lib.
Ведь модель заточена под работу с какой-то конкретной таблицей из БД, а в другом приложении она (таблица) может иметь другую структуру, все равно нужно писать немного другую модель, так что все что лежит в lib, получается что, я использую на всех сайтах а то что в app необходимо, только в этом конкретном приложении и все таки нестоит выносить, пусть даже немного придется повториться, как правило получается не полностью идентичный код.
Спасибо за комментарий.