⬆️ ⬇️

Creating easy access to resources from a ZF controller

It would be very nice to be able to access resources loaded into bootstrap from application controllers. For example, I would like to access the “DB” resource from the controller as follows $ this-> db;

To do this, we write Action Helper, which will load certain resources into the application controller:

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' );

}

}




* This source code was highlighted with Source Code Highlighter .




and initialize it in bootstrap:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap

{

protected function _initResourceInjector()

{

Zend_Controller_Action_HelperBroker::addHelper(

new My_ResourceInjector(array(

'db' ,

'layout' ,

'navigation' ,

));

);

}

}




* This source code was highlighted with Source Code Highlighter .


The code above will create links to resources: db, layout, and navigation. This means that you can now access them directly from the controllers.

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,

);

}



// ...

}




* This source code was highlighted with Source Code Highlighter .


This solution leads to some simplification - now there is no need to pull the bootstrap out of the initialization object, and then pull out the resource.

But, this solution has several problems: How do we know what resources were associated with the controller? How can we control this?

From here, the decision follows to create a pool of necessary resources for the controller.



New Action Helper resource download will now look like this:

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' );

}

}




* This source code was highlighted with Source Code Highlighter .


You still have to register it with bootstrap, but now without specifying a list of resources:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap

{

protected function _initResourceInjector()

{

Zend_Controller_Action_HelperBroker::addHelper(

new My_ResourceInjector();

);

}

}




* This source code was highlighted with Source Code Highlighter .


Instead, the required list of resources you now define in the controller itself:

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,

);

}



// ...

}




* This source code was highlighted with Source Code Highlighter .


This creates a clearer understanding of what resources are needed by the controller, and also, each controller receives exactly the resources that it will use.



Another improvement that we can add to the resource loader is that if a dependent resource was not found, an exception will be thrown:

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' );

}

}




* This source code was highlighted with Source Code Highlighter .


')

This gives us a better understanding and tracking of dependent resources. Resources are determined by the object that needs them, and the missing resources will cause an exception.



One potential improvement that can be made is an indication of the list of resources that are automatically downloaded for each controller. To implement this, it will be necessary to merge the default list with the resources defined in the controller. I leave this task to my readers.



The area of ​​Action Helpers is poorly explored by ZF users. I hope this post shows how strongly Action Helpers can automate repetitive and common tasks.



This article is a partial translation of the article by Matthew Weier O'Phinney A Simple Resource Injector for ZF Action Controllers .

Source: https://habr.com/ru/post/88426/



All Articles