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

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

  Все выпуски  

ZEND FRAMEWORK: Расширение файла начальной загрузки


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

В свое время мы разработали файл начальной загрузки нашего приложения (см. Пример 4.7, «Файл начальной загрузки»). Однако, тогда мы ограничились лишь самым необходимым: главным контроллером Zend_Controller_Front. Впрочем, в последующем некоторые косметические правки предлагалось внести при выполнении контрольных заданий (см. «Ответы и решения к Глава 4, Быстрый старт», Задания 8 и 9; «Ответы и решения к Глава 7, Класс Zend», Задание 2; «Ответы и решения к Глава 12, Класс Zend_Log», Задание 2).

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

Обычно определения классов в PHP приложениях вынесены в отдельные файлы, которые, прежде чем использовать данные классы, необходимо включить в основной скрипт. В результате в начале каждого скрипта появляется длинная череда выражений require_once или им подобных, управлять которой достаточно обременительно. Соответственно, возрастает и вероятность возникновения ошибок.

К счастью, в PHP 5 появилась магическая функция автозагрузки объектов __autoload(), позволяющая автоматизировать процесс включения файлов с определениями классов и скрыть его внутри самой функции. При этом следует придерживаться определенных соглашений о названиях классов и файлов, в которых они определены. Если эти названия совпадают, то, в простейшем виде, функция может выглядеть следующим образом.

<?php

function __autoload($class) 1
{
    require "$class.php"; 2
}

?>
        
1

Магическая функция вызывается автоматически при попытке использования класса, определение которого отсутствует. В качестве аргумента функции передается название отсутствующего класса.

2

Включение файла с отсутствующим определением. Выражение require (вместо require_once) здесь допустимо использовать, так как, если бы включаемый файл уже был включен ранее, то магическая функция вообще не была бы вызвана.

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

<?php

function __autoload($class)
{
    $pathname = strtr($class, '_', DIRECTORY_SEPARATOR); 1
    require "$pathname.php";
}

?>
        

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

Впрочем, в Zend Framework существует уже готовый метод для загрузки классов (см. «Метод Zend::loadClass()»). При условии его использования функция автозагрузки примет следующий вид.

<?php

function __autoload($class)
{
    require_once 'Zend.php'; 1
    Zend::loadClass($class);
}
        
1

Файл с определением самого класса Zend приходится включать все же вручную.

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

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

<?php

require_once 'Zend.php';

function __autoload($class)
{
    Zend::loadClass($class);
}
        
[Подсказка]Подсказка

Дополнительная информация об автозагрузке может быть найдена здесь.

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

Обработка исключительных ситуаций в PHP 5 производится при помощи структуры try...catch. Собственно исполнение приложения (запуск главного контроллера) помещается в блок try, а реакция на возникающие исключительные ситуации - в блок catch.

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

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

<?php

try {
    Zend_Controller_Front::run(ZF_CONTROLLERS);
} catch (Exception $e) {
     header('Location: http://pterodactyl.l2p.net/'); 1
}
        
1

Переадресация на домашнюю страницу в случае возникновения ошибки представляется вполне логичной.

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

Дополнительная информация об исключительных ситуациях может быть найдена здесь.

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

«Общение» с разного рода серверами (базы данных, почтовым и др.) также требует указания различных настроек (адрес сервера, порт, имя пользователя, пароль и пр.). Достаточно «емкими» в смысле настроек выглядят и часто используемые вместе с Zend Framework системы шаблонов (Smarty, Flexy и т. п.).

При смене хостинга (и даже при изменении локальных характеристик) многие, если не все, из этих настроек будут нуждаться в исправлении. Конечно же, редактирование файла начальной загрузки - далеко не лучший способ, если заботиться о надежности приложения. Правильнее было бы вынести все настройки в отдельный файл и подгружать их оттуда. Zend Framework обладает готовым инструментом для такого решения (см. Глава 11, Класс Zend_Config).

Для хранения настроек выберем формат .ini файла и назовем его (как бы Вы думали?) config.ini. Проще всего было бы расположить этот файл в одной директории с файлом начальной загрузки index.php (т. е. в корневой директории сайта). Однако, это выглядит несколько сомнительно с точки зрения безопасности; особенно, если учесть, что со временем там могут находиться пароли к базам данных и прочая достаточно деликатная информация. Поэтому разместим этот файл в директории application. Для этого придется пойти на небольшие жертвы в виде чуть более громоздкого кода.

[Внимание]Внимание

Приведенный ниже код нуждается в версии Zend Framework 0.2.0. Об изменениях в новой версии см. Приложение B, Изменения в Zend Framework 0.2.0 (в частности, «Класс Zend_Config»).

[dirs]
; MVC directories (related to ZF_APP)
models = /models
views = /views
controllers = /controllers
        
<?php

// requires Zend Framework 0.2.0

define('ZF_ROOT', realpath($_SERVER['DOCUMENT_ROOT'].'/../'));
define('ZF_LIBRARY', ZF_ROOT.'/library');
define('ZF_APP', ZF_ROOT.'/application');

set_include_path(get_include_path().PATH_SEPARATOR.ZF_LIBRARY);

$cfgDirs = new Zend_Config_Ini(ZF_APP.'/config.ini', 'dirs');

Zend_Controller_Front::run(ZF_APP.$cfgDirs->controllers);
        
[Подсказка]Подсказка

Для получения дополнительной информации о классе Zend_Config см. Глава 11, Класс Zend_Config.

Из всех доступных способов сохранения информации выберем сохранение в файл (как наиболее доступный и практичный). Название и расположение этого файла зададим в конфигурации.

[Внимание]Внимание

Не забудьте позаботиться о возможности записи в этот файл. Например, создайте пустой файл и установите права доступа к нему в 0777.

[log]
file = /error.log   ; related to ZF_APP
        
<?php

$cfgLog = new Zend_Config_Ini(ZF_APP.'/config.ini', 'log');

Zend_Log::registerLogger(new Zend_Log_Adapter_File(ZF_APP.$cfgLog->file));
        

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

    $record = strftime('%D %T') . ' ' . $e->getMessage();
    Zend_Log::log($record, Zend_Log::LEVEL_ERROR);
        

В результате при возникновении ошибки в логе увидим что-нибуль наподобие этого сообщения.

12/15/06 16:19:17 BookController::errorAction() does not exist
    and was not trapped in __call()., ERROR
        
[Подсказка]Подсказка

Для получения дополнительной информации о классе Zend_Log см. Глава 12, Класс Zend_Log.

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

В качестве адаптера переднего плана используем Zend_Cache_Frontend_Page, в качестве фонового - Zend_Cache_Backend_File. Параметры зададим в конфигурационном файле.

[cache]
front.lifeTime = 3600
back.cacheDir = ZF_CACHE
        
<?php

define('ZF_CACHE', ZF_ROOT.'/tmp');

$cfgCache = new Zend_Config_Ini(ZF_APP.'/config.ini', 'cache');

$frontOptions = array();
foreach ($cfgCache->front as $option => $value) {
    $frontOptions[$option] = $value;
}
$backOptions = array();
foreach ($cfgCache->back as $option => $value) {
    $backOptions[$option] = $value;
}
$cache = Zend_Cache::factory('Page', 'File', $frontOptions, $backOptions);
$cache->start();
        
[Подсказка]Подсказка

Для получения дополнительной информации о классе Zend_Cache см. Глава 14, Класс Zend_Cache.



Created with DocBook


В избранное