01. Начало


ZendFramework    На протяжении серии статей будет подробно рассмотрена, от начала и до конца, разработка приложения с использованием Zend Framework. То что получилось, доступно по адресу zf-demo.2developers.net. Результатом этой статьи станет так называемый Hello World на Zend'e, в следующих статьях будем наращивать функционал, используя различные компоненты ZF. Если вы никогда не имели дела с ZF, то что бы понять о чем идет речь и нужно ли вам это, попробуйте Quick Start.
    Зачем это? Когда я только начал работать с 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.


Прикрепленные файлы:

Исходники (+структура каталогов) (Загрузок: 171)

Добавлена: 23-01-2009 | Изменена: 16-02-2009 | Пользователем: djaarf | Просмотров: 6697

Комментарии

amigo 13-02-2009 18:29
Сделал, работает, но можно о струтуре побольше написать, а то неясно что для чего, ведь она не такая как советует Zend
djaarf 13-02-2009 21:16
ответ Amigo: Ок. Пока так, просто структура в дальнейшем будет дополняться по мере появления нового функционала, там уже будет расписано более подробно.
Ivan 05-03-2009 01:39
Поддерживаю целиком и полностью со структурой приложения, я тоже к этому в свое время пришел.
Stepan Tanasiychuk 25-03-2009 05:53
Вызывать переопределенный divoInit() наследника в методе init() предка не совсем верно. Правильнее в методе init() наследников вызывать parent::init() предка.
djaarf 25-03-2009 14:08
Stepan Tanasiychuk, да вы правы, но я просто повторил за разработчиками ZF. Ведь они в конструкторе Zend_Controller_Action посчитали приемлемым вызывать метод init(), вот и я сделал то же самое, только на уровень ниже. Все в духе ZF ;)
Roman 23-04-2009 08:23
я бы перенес папку с моделями (да и другие общие для приложения) из app в lib, чтобы не дублировать файлы в случае использования модулей. А вообще очень полезное начинание, информации по zf для новичков на русском маловато.
djaarf 23-04-2009 13:58
Roman,  когда у меня на хостинге появилось 2-е и 3-е приложение работающее с библиотекой ZF, её пришлось вынести в корень и тогда полностью стало понятно для чего нужна папка app и lib.
Ведь модель заточена под работу с какой-то конкретной таблицей из БД, а в другом приложении она (таблица) может иметь другую структуру, все равно нужно писать немного другую модель, так что все что лежит в lib, получается что, я использую на всех сайтах а то что в app необходимо, только в этом конкретном приложении и все таки нестоит выносить, пусть даже немного придется повториться, как правило получается не полностью идентичный код.

Спасибо за комментарий.


Оставить комментарий



Капча *

Captcha

Комментарий будет опубликован после проверки модератором

Для подсветки синтаксиса исходный код следует обрамлять следующими тэгами
<pre><code class="синтаксис" >код</code></pre>
Подерживаются следующие: cpp php javascript sql html-xml css ini