Zend Framework 2 : Automatic Controller Invokables via Abstract Factories
Before you continue reading, you should know that this is just to handle if you forgot to mention/register your controller in invokables/factories. Being explicit is more secure and reliable.
Ok then, let’s start. One of the Zend Framework Service Managers keys is abstract_factories. An abstract factory can be considered a “fallback” – if the service does not exist in the manager, it will then pass it to any abstract factories attached to it until one of them is able to return an object. For example, we want to automatic register class of our controllers of our application if we forgot to register in invokables.
1. Create an abstract factories
//module/SanCommons/src/SanCommons/Services/CommonControlAppAbstractFactory.php
namespace SanCommons\Services;
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class CommonControlAppAbstractFactory implements AbstractFactoryInterface
{
public function canCreateServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName)
{
if (class_exists($requestedName.'Controller')){
return true;
}
return false;
}
public function createServiceWithName(ServiceLocatorInterface $locator, $name, $requestedName)
{
$class = $requestedName.'Controller';
return new $class;
}
}
2. Register to getControllerConfig()
//module/SanCommons/Module.php
namespace SanCommons;
class Module
{
public function getControllerConfig()
{
return array(
'abstract_factories' => array(
'SanCommons\Services\CommonControlAppAbstractFactory'
),
);
}
public function getAutoloaderConfig(){ /*common code*/}
public function getConfig(){ /*common code*/}
}
Remember, ‘controllers’ and ‘ModuleManager’ are the services that composed automatically by mvc stack. So, if route found a match ‘/:controller’ segment, ServiceManager will find a Service that named the Name of The Controller that pass in url in ‘controllers’ => ‘invokables’ key.
//module/SanCommons/config/module.config.php
return array(
'controllers' => array(
'invokables' => array(
'YourModule\Controller\A' => 'YourModule\Controller\AController',
'YourModule\Controller\B' => 'YourModule\Controller\BController',
/*.. etc ...*/
),
),
),
The controllers services named ‘YourModule\Controller\A’, etc. Whenever you forgot to mention/register that in ServiceManager, ServiceManager will find it in the ‘Limbo’ (abstract_factories). If the abstract factory returns true to the canCreateServiceWithName method the service manager will create a service via createServiceWithName method.
For example : If we just created a controller with end with ‘Controller’, for example, TestAutoController, and forgot to register it into invokables, The Controller will automatically getted because service automatically created.
What if we want other service that not in Mvc Stack, and need to be called by ServiceLocator with ‘hand’
? create abstract factory and register into abstract_factories under getServiceConfig().
Done !
References :
1. http://akrabat.com/zend-framework-2/zendservicemanager-configuration-keys/
2. http://zf2.readthedocs.org/en/latest/modules/zend.service-manager.intro.html
3. http://www.stephenrhoades.com/?p=513
4. http://www.framework.zend.com/manual/2.0/en/user-guide/routing-and-controllers.html
5. http://framework.zend.com/manual/2.0/en/modules/zend.mvc.quick-start.html#create-a-route
sorry for post here, i have a issue with form upload + password field when EDIT.
When i edit form and nothing change for: password + image upload form, it become NULL.
How to fix it, please ?
just don’t update the db if it is nothing change.
can u show me a concrete example, it’s perfect if you make a project tutorial like JOBEET SYMFONY
if (is_null($data['password'])) unset($data['password']); $this->update($data, array('id' => $id));Thanks for the suggestion
[...] http://samsonasik.wordpress.com/2012/12/23/zend-framework-2-automatic-controller-invokables-via-abst… [...]
Hi Abdul!
I´m quite new in Zend development, and I´m using yours tutorials to guide me into Zend world!
So, I´ve read this tutorial about Abstract Factories and I understand how pretty and useful it is, but my knowledge is just too litlle that I can´t realize how I should use this class, where I must configure it, and how can I use it.
Coul you provide me a little example of using this classes and where I need to setup it to do so?
I have updated the code i provide with comment the code place addition, hope helpful.
What I dont understand is why in ZF2 I need to register my controller into a invokable? this are controller, their main purpose in life is to be invoked… what are we doing with an uninvokable controller anyway?
read the docs : http://framework.zend.com/manual/2.1/en/modules/zend.mvc.quick-start.html#create-a-route we talk about this: “We inform the application about controllers we expect to have in the application. This is to prevent somebody requesting any service the ServiceManager knows about in an attempt to break the application. The dispatcher uses a special, scoped container that will only pull controllers that are specifically registered with it, either as invokable classes or via factories.”
as Matthew Weier ‘Ophinney answer (http://www.framework.zend.com/manual/2.1/en/user-guide/routing-and-controllers.html#comment-706138835) , this is :
1. to be explicit about what controllers are available
2. to be secure by default.
if you want to discuss it, you may bring to the zend framework mailing list : http://zend-framework-community.634137.n4.nabble.com/