|
I have a couple of instances where I have a Service from one Module which extends a Service from another. However it also needs the flexibility to not require the extending module on some projects. Using DI this worked quite well:
Service 1:
namespace Module1\Service;
class MyService1 {…}
Config 1: 'di' => array( 'instance' => array( 'alias' => array( 'myService' => 'Module1\Service\MyService1', ), 'myService' => array( 'injectSomething' => 'Something', ), ), ), Service 2:
namespace Module2\Service;
use Module1\Service\Service1;
class MyService2 extends Service1 {…}
Config 2: 'di' => array( 'instance' => array( 'alias' => array( 'myService' => 'Module2\Service\MyService2', ), 'myService' => array( 'injectSomethingElse' => 'SomethingElse', ), ), ), The problem comes when using the ServiceManager. To inject stuff from both modules I would need two separate factories, however then I have the problem of dependencies needing injecting on both. Inheriting off the first module's factory won't work because it would create an instance of the first module's service rather than the second module's extended instance of the first. Factory 1:
class Service1Factory implements FactoryInterface
{
public function createService( ServiceLocatorInterface $serviceLocator )
{
$service = new Service1();
$service->setSomething( 'Something' );
return $service;
}
}
Factory 2:
use Module2\Service\Service1Factory;
class Service2Factory extends Service1Factory
{
public function createService( ServiceLocatorInterface $serviceLocator )
{
$service = parent::createService( $serviceLocator ); // doh, wrong instance
$service->setSomethingElse( 'SomethingElse' );
return $service;
}
}
The inheritance solution does work however if I create a stub/endpoint service class within my application class which the factory instantiates and it has the correct inheritance: Application\Service\MyService > Module2\Service\Service2 > Module1\Service\Service1 or Application\Service\MyService > Module1\Service\Service1 I don't think this is a great solution as it forces the need to create them within the application module for each project to get it working. Using this solution has further escalating issues from inherited objects (such as forms) in both modules needing injecting into the service instance. Do I do the same thing for the forms and create a stub/endpoint form in the application module as well? It starts getting a bit bloated and untidy. Form1 (injected into Service1):
namespace Module1\Form;
class Form1 {…}
Form2 (Injected into Service2):
namespace Module2\Form;
use Module1\Form\Form1;
class Form2 extends Form1 {…}
Any thoughts? |
|
This post has NOT been accepted by the mailing list yet.
This post was updated on .
One way to solve this would be to use a common factory for the super type and all extended services. You could then implement some logic based around configuration that decided which instance to create and what to set. This would break the module separation rule though.
Another solution could be to add an array to the supertype which extending service factories add to, i.e super type factory protected $array = array('create class'=>'supertype','inject' => array( 'class 1','class 2' ) ); function createService( ServiceLocatorInterface $serviceLocator ) { $service = new $this->array['class']; foreach($this->array['inject'] as $class){ $service->set($locator->get($class); } return $service; } then the extended factory createService method could look similar to: function createService( ServiceLocatorInterface $serviceLocator ) { $this->array['class'] = 'theExtendedClass'; $this->array['inject'][] = 'anotherService'; return parent::createService($locator); } regards |
| Powered by Nabble | Edit this page |
