Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Zend\Db\Adapter\AdapterServiceFactory always invoke Zend\Db\Adapter\Adapter #353

Open
raivirtual opened this issue Jan 27, 2019 · 4 comments

Comments

@raivirtual
Copy link

raivirtual commented Jan 27, 2019

I created my own Db\Adapter\AdapterServiceFactory so I could be able to call my own Db\Adapter.

namespace RVMvp\Db\Adapter;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Zend\Db\Adapter\AdapterServiceFactory as ZendAdapterServiceFactory;

class AdapterServiceFactory extends ZendAdapterServiceFactory
{
    public function createService(ServiceLocatorInterface $container)
    {
        return $this($container, Adapter::class);
    }
}

It should create a service of RVMvp\Db\Adapter\Adapter but keep creating Zend\Db\Adapter\Adapter.

This is happening because the invokable method is calling directly the Zend\Db\Adapter\Adapter instead of the requested name provided on createService method:

namespace Zend\Db\Adapter;

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class AdapterServiceFactory implements FactoryInterface
{
    /**
     * Create db adapter service
     *
     * @param ContainerInterface $container
     * @param string $requestedName
     * @param array $options
     * @return Adapter
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $config = $container->get('config');
        return new Adapter($config['db']); // HERE IT'S CALLING DIRECTLY
    }

    /**
     * Create db adapter service (v2)
     *
     * @param ServiceLocatorInterface $container
     * @return Adapter
     */
    public function createService(ServiceLocatorInterface $container)
    {
        return $this($container, Adapter::class);
    }
}

I did my workaround adding the invokable method to my own AdapterServiceFactory:

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
 {
        $config = $container->get('config');
        return new $requestedName($config['db']); // CHANGED TO REQUESTED NAME
 }

I'm suggesting a bugfix so we don't need to override the invokable method.

@alextech
Copy link
Contributor

I did my workaround adding the invokable method to my own AdapterServiceFactory:

That is how Service Manager expects factories to be. Depending on how you configured your service manager, this is not be a problem. I am guessing you have

invokables => [ RVMvp\Db\Adapter\AdapterServiceFactory::class]

somewhere in your module confugration?

@raivirtual
Copy link
Author

But it's not calling by Service Manager. It's instancing directly.

@pine3ree
Copy link
Contributor

pine3ree commented Mar 4, 2019

Hello @raivirtual , You should define a factory for the adapter interface:

'dependencies' => [
    //...
    'factories' => [
        //...
        \Zend\Db\Adapter\AdapterInterface::class => \My\Db\AdapterFactory::class,
        //...
    ],
    //...
],

In servicemanager config the Zend\Db\Adapter\Adapter::class service name is actually an alias for Zend\Db\Adapter\AdapterInterface::class::class (see ConfigProvider in zend-db), but you should build your dependencies upon the AdapterInterface::class interface as service name.
kind regards

@weierophinney
Copy link
Member

This repository has been closed and moved to laminas/laminas-db; a new issue has been opened at laminas/laminas-db#21.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants