assumption: Event\Service\EventService
is my personal object that works with Event\Entity\Event
entities
This code works in an ActionController:
$eventService = $this->getServiceLocator()->get('Event\Service\EventService');
How can I get $eventService
in a Zend\Form\Form
in the same way?
You have two options if you have a dependency like this. In your case, a Form
depends on a Service
. The first option is to inject dependencies:
class Form
{
protected $service;
public function setService(Service $service)
{
$this->service = $service;
}
}
$form = new Form;
$form->setService($service);
In this case, the $form
is unaware of the location of $service
and generally accepted as a good idea. To make sure you don't need to set up all the dependencies yourself each time you need a Form
, you can use the service manager to create a factory.
One way (there are more) to create a factory is to add a getServiceConfiguration()
method to your module class and use a closure to instantiate a Form
object. This is an example to inject a Service
into a Form
:
public function getServiceConfiguration()
{
return array(
'factories' => array(
'Event\Form\Event' => function ($sm) {
$service = $sm->get('Event\Service\EventService');
$form = new Form;
$form->setService($service);
return $form;
}
)
);
}
Then you simply get the Form
from your service manager. For example, in your controller:
$form = $this->getServiceLocator()->get('Event\Form\Event');
A second option is to pull dependencies. Though it is not recommended for classes like forms, you can inject a service manager so the form can pull dependencies itself:
class Form
{
protected $sm;
public function setServiceManager(ServiceManager $sm)
{
$this->sm = $sm;
}
/**
* This returns the Service you depend on
*
* @return Service
*/
public function getService ()
{
return $this->sm->get('Event\Service\EventService');
}
}
However, this second option couples your code with unnecessary couplings and it makes it very hard to test your code. So please use dependency injection instead of pulling dependencies yourself. There are only a handful of cases where you might want to pull dependencies yourself :)
You can just configure the form with all the options in the module.php. In the following code I:
- Name the service as my_form
- Associate the new object \MyModule\Form\MyForm with this service
- Inject the service 'something1' to the _construct()
- Inject the service 'something2' to the setSomething()
Code:
public function getServiceConfiguration()
{
return array(
'factories' => array(
'my_form' => function ($sm) {
$model = new \MyModule\Form\MyForm($sm->get('something1'));
$obj = $sm->get('something2');
$model->setSomething($obj);
return $model;
},
),
);
}
And then in the controller the following line will populate your object with all needed dependencies
$form = $this->getServiceLocator()->get('my_form');
Use the form element manager to get the form in your controller:
$form = $this->getServiceLocator()->get('FormElementManager')->get('Path\To\Your\Form', $args);
Then in your form will become this
<?php
namespace Your\Namespace;
use Zend\Form\Form;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ ServiceLocatorAwareTrait;
class MyForm extends Form implements ServiceLocatorAwareInterface {
use ServiceLocatorAwareTrait;
public function __construct($class_name, $args)
{
/// you cannot get the service locator in construct.
}
public function init()
{
$this->getServiceLocator()->get('Path\To\Your\Service');
}
}