Search code examples
phppdodependency-injectionzend-framework2

Zend2 Dependency injection factory to service


Im trying to implement Dependency injection Using the Zend2 service manager. I want to inject a PDO instance into Service (Im not using the Zend Db).

Im following the tutorial here: https://framework.zend.com/manual/2.4/en/in-depth-guide/services-and-servicemanager.html

I have it working for another service, but the when injecting the PDO instance Im getting this error:

Catchable fatal error: Argument 1 passed to Application\Service\DataService::__construct() must be an instance of Application\Service\DbConnectorService, none given, called in /srv/www/shared-apps/approot/apps-dev/ktrist/SBSDash/vendor/zendframework/zendframework/library/Zend/ServiceManager/ServiceManager.php on line 1077 and defined in /srv/www/shared-apps/approot/apps-dev/ktrist/SBSDash/module/Application/src/Application/Service/DataService.php on line 24

From the tutorial this seems to be related to my invokeables in the module.config. But I cannot work out what the issue is.

Any advice is appreciated.

Here is my code:

DataService:

class DataService {
protected $dbConnectorService;

public function __construct(DbConnectorService $dbConnectorService) {
    $this->dbConnectorService = $dbConnectorService;
}
......

DataServiceFactory:

namespace Application\Factory;

use Application\Service\DataService;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class DataServiceFactory implements FactoryInterface {

function createService(ServiceLocatorInterface $serviceLocator) {
    $realServiceLocator = $serviceLocator->getServiceLocator();
    $dbService = $realServiceLocator->get('Application\Service\DbConnectorService');

    return new DataService($dbService);
}

}

Module.Config:

'controllers' => array(
'factories' => array(
        'Application\Controller\Index' => 'Application\Factory\IndexControllerFactory',
        'Application\Service\DataService' => 'Application\Factory\DataServiceFactory',
    )
),
    'service_manager' => array(
    'invokables' => array(
        'Application\Service\DataServiceInterface' => 'Application\Service\DataService',
        'Application\Service\DbConnectorService' => 'Application\Service\DbConnectorService',
    )
),

Solution

  • You are trying to create the service as an 'invokable' class. ZF2 will treat this service as a class without dependencies (and not create it using the factory).

    You should update your service configuration to register under the 'factories' key, pointing to the factory class name.

    'service_manager' => [
        'invokables' => [
            'Application\\Service\\DbConnectorService'
                => 'Application\\Service\\DbConnectorService',
        ],
        'factories' => [
            'Application\\Service\\DataServiceInterface' 
                => 'Application\\Factory\\DataServiceFactory',
        ],
    ],
    

    You will need to make the same change for DbConnectorService if that also has a factory.