Controller Plugin for Configuration Array Access

Published on Nov 28, 2016

Controller Plugin for Configuration Array Access

Plugin to access configuration arrays in controllers.


I use configuration arrays to keep application wide settings in my Zend Framework applications like items_per_page to use with pagination, or secret keys, or any other variable that I don't want to keep in the database but directly in the file system.

At the beginning I started injecting configuration array into the controllers by using controller factories. However this requires to do same thing for every single controller. Then I learned there is a better way and that's where I met Controller Plugins

Here is how I created a controller plugin I called as application. Everything below is applied on a clean Zend Framework Skeleton Application.

Started with creating the folder /module/Application/src/Controller/Plugin and Application.php class module in this location. Assigning the $settings variable in the plugin constructor for now.

# /module/Application/src/Controller/Plugin/Application.php
<?php namespace Application\Controller\Plugin; use Zend\Mvc\Controller\Plugin\AbstractPlugin; use Zend\Config\Config; class Application extends AbstractPlugin { protected $settings; public function __construct() { $settings = [ 'pagination' => [ 'itemsPerPage' => 13, ], ]; $this->settings = new Config($settings); } public function getSettings() { return $this->settings; } }

Now I need to introduce the plugin to my module in the module configuration file.

# /module/Application/src/config/module.config.php
<?php namespace Application; use Zend\ServiceManager\Factory\InvokableFactory; return [ // ... 'controller_plugins' => [ 'aliases' => [ 'application' => Controller\Plugin\Application::class, ], 'factories' => [ Controller\Plugin\Application::class => InvokableFactory::class, ], ], // ... ];

Note that plugin is defined as InvokableFactory so far. I am going to change it when it is time to inject settings configuration variable via plugin's factory. Not there yet. I just have a plugin that could be called within any controller action that will return settings array defined in the plugin's constructor. It is good time to test it in the application module's IndexController.

# /module/Application/src/Controller/IndexController.php
<?php public function indexAction() { return new ViewModel([ 'itemsPerPage' => $this->application()->getSettings()->pagination->itemsPerPage ]); }

Zend\Config\Config used in the plugin constructor helps me to use the object notation above. This way I can now use $this->itemsPerPage variable in my view script and it will return 13 as defined in the provided configuration array.

It's great but the configuration array will actually defined in the global.php file autoloaded by my application. So I have to read it prior to create my plugin and inject it to its constructor instead defining directly in the constructor.

I should define the configuration array in the global.php file first.

# /config/autoload/global.php
<?php return [ // ... 'application' => [ 'settings' => [ 'pagination' => [ 'itemsPerPage' => 13, ], ], ], // ... ];

Whenever I need to inject something to my controllers, mappers, hydrators and plugins, I need to create corresponding Factory. In this case, I have to inject this configuration array defined in the global.php to my plugin. So let's create the ApplicationFactory.php file in /module/Application/src/Controller/Plugin/Factory.

# /module/Application/src/Controller/Plugin/Factory/ApplicationFactory.php
<?php namespace Application\Controller\Plugin\Factory; use Zend\ServiceManager\Factory\FactoryInterface; use Interop\Container\ContainerInterface; use Application\Controller\Plugin\Application; class ApplicationFactory implements FactoryInterface { public function __invoke(ContainerInterface $container, $requestedName, array $options = null) { $config = $container->get('config'); $settings = $config['application']['settings']; $plugin = new Application($settings); return $plugin; } }

$container reads the configuration array for me and I pull the settings array I set up in global.php then create the Application plugin by injecting in it. Finally return the $plugin.

I need to change my plugin code to accept this injected variable as $setting instead defining it in the constructor to make it work.

# /module/Application/src/Controller/Plugin/Application.php
<?php namespace Application\Controller\Plugin; use Zend\Mvc\Controller\Plugin\AbstractPlugin; use Zend\Config\Config; class Application extends AbstractPlugin { protected $settings; public function __construct($settings) { $this->settings = new Config($settings); } public function getSettings() { return $this->settings; } }

Finally need to tell my module to create the plugin by using its dedicated factory instead as an InvokableFactory.

# /module/Application/src/config/module.config.php
<?php namespace Application; return [ // ... 'controller_plugins' => [ 'aliases' => [ 'application' => Controller\Plugin\Application::class, ], 'factories' => [ Controller\Plugin\Application::class => Controller\Plugin\Factory\ApplicationFactory::class, ], ], // ... ];

Factory didn't change how the plugin is used in the view script, it still provides the necessary information by using the $this->application()->getSettings()->pagination->itemsPerPage object notation. However, now the setting is in the autoloaded global.php configuration file.


*** I'd be happy to know if this content helped you or anything else about it to tell me. Please also feel free to share it by using the buttons below if you think it might help others too.


 
Worked with Zend Framework 3