Создание простого доступа к ресурсам из ZF контроллера
Было бы очень хорошо иметь возможность доступа к загружаемым в bootstrap ресурсам из контроллеров приложения. Например, я хотел бы получить доступ к "DB" ресурсу из контроллера следующим образом $this->db;
Для этого напишем Action Helper, который будет загружать определенные ресурсы в контроллер приложения:
-
class My_ResourceInjector extends Zend_Controller_Action_Helper_Abstract
-
{
-
protected $_resources;
-
-
public function __construct(array $resources = array())
-
{
-
$this->_resources = $resources;
-
}
-
-
public function preDispatch()
-
{
-
$bootstrap = $this->getBootstrap();
-
$controller = $this->getActionController();
-
foreach ($this->_resources as $name) {
-
if ($bootstrap->hasResource($name)) {
-
$controller->$name = $bootstrap->getResource($name);
-
}
-
}
-
}
-
-
public function getBootstrap()
-
{
-
return $this->getFrontController()->getParam('bootstrap');
-
}
-
}
и инициализируем его в bootstrap:
-
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
-
{
-
protected function _initResourceInjector()
-
{
-
Zend_Controller_Action_HelperBroker::addHelper(
-
new My_ResourceInjector(array(
-
'db',
-
'layout',
-
'navigation',
-
));
-
);
-
}
-
}
Код выше, создаст ссылки на ресурсы: db, layout и navigation. Это значит, что теперь вы можете получить к ним прямой доступ из контроллеров.
-
class FooController extends Zend_Controller_Action
-
{
-
public function barAction()
-
{
-
$this->layout->disableLayout();
-
$model = $this->getModel();
-
$model->setDbAdapter($this->db);
-
$this->view->assign(
-
'model' => $this->model,
-
'navigation' => $this->navigation,
-
);
-
}
-
-
// ...
-
}
Этото решение ведет к некоторому упрощению - теперь нет необходимости вытягивать bootstrap из объекта инициализации, а потом вытягивать ресурс.
Но, у этого решения есть несколько проблем: Откуда мы знаем, какие ресурсы были связаны с контроллером? Как мы можем это контролировать?
Отсюда, вытекает решение создать пул необходимых ресурсов для контроллера.
Новый Action Helper загрузки ресурсов теперь будет выглядеть так:
-
class My_ResourceInjector extends Zend_Controller_Action_Helper_Abstract
-
{
-
protected $_resources;
-
-
public function preDispatch()
-
{
-
$bootstrap = $this->getBootstrap();
-
$controller = $this->getActionController();
-
-
if (!isset($controller->dependencies)
-
|| !is_array($controller->dependencies)
-
) {
-
return;
-
}
-
-
foreach ($controller->dependencies as $name) {
-
if ($bootstrap->hasResource($name)) {
-
$controller->$name = $bootstrap->getResource($name);
-
}
-
}
-
}
-
-
public function getBootstrap()
-
{
-
return $this->getFrontController()->getParam('bootstrap');
-
}
-
}
Вы все еще должны зарегистрировать его в bootstrap, но теперь уже без указанаия списка ресурсов:
-
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
-
{
-
protected function _initResourceInjector()
-
{
-
Zend_Controller_Action_HelperBroker::addHelper(
-
new My_ResourceInjector();
-
);
-
}
-
}
Вместо этого, необходимый список ресурсовы вы теперь определяете в самом контроллере:
-
class FooController extends Zend_Controller_Action
-
{
-
public $dependencies = array(
-
'db',
-
'layout',
-
'navigation',
-
);
-
-
public function barAction()
-
{
-
$this->layout->disableLayout();
-
$model = $this->getModel();
-
$model->setDbAdapter($this->db);
-
$this->view->assign(
-
'model' => $this->model,
-
'navigation' => $this->navigation,
-
);
-
}
-
-
// ...
-
}
Это создает более четкое понимание какие ресурсы необходимы контроллеру, а также, каждый контроллер получает именно те ресурсы, которые он будет использовать.
Еще одно улучшение, которое мы можем добавить к загрузчику ресурсов - это, если зависимый ресурс не был найден, будет вызвано исключение:
-
class My_ResourceInjector extends Zend_Controller_Action_Helper_Abstract
-
{
-
protected $_resources;
-
-
public function preDispatch()
-
{
-
$bootstrap = $this->getBootstrap();
-
$controller = $this->getActionController();
-
-
if (!isset($controller->dependencies)
-
|| !is_array($controller->dependencies)
-
) {
-
return;
-
}
-
-
foreach ($controller->dependencies as $name) {
-
if (!$bootstrap->hasResource($name)) {
-
throw new DomainException("Unable to find dependency by name '$name'");
-
}
-
$controller->$name = $bootstrap->getResource($name);
-
}
-
}
-
-
public function getBootstrap()
-
{
-
return $this->getFrontController()->getParam('bootstrap');
-
}
-
}
Это дает нам лучшение понимание и отслеживания зависимых ресурсов. Ресурсы определяются объектом, который в них нуждается, а недостающие ресурсы будут вызывать исключение.
Одно потенциальное улучшение, которое можно сделать, это указание списока ресурсов загружаемых автоматически для каждого контроллера. Для реализации этого, необходимо будет объеденить список по умолчанию с ресурсами определенными в контроллрере. Эту задачу я оставляю для моих читателей.
Область Action Helpers является слабо исследованной ZF пользователями. Надеюсь, этот пост покажет как сильно Action Helpers могут автоматизировать повторяемые и общте задачи.
Эта статья является частичным перевод статьи Matthew Weier O'Phinney A Simple Resource Injector for ZF Action Controllers.

>>Область Action Helpers является слабо исследованной ZF пользователями.
В последнее время мне да и не только мне кажется что ЗФ стал походить на космический корабль от которого обычный среднестатистический человек использует 3 на максимум 5 гаеек, судя по статье таких людей просто пруд пруди
Но в то же время, гайки используються разные разными разработчиками - это космический корабль из жидкого пластилина так сказать, и во что он в итоге кристализуется зависит от опыта разработчика и немного от удачи :)