0

I'm using more than one database. So I have this kind of configuration in my global.php file:

return [
'db' => [
    ...
    ],
    'adapters' => [
        'adapter1' => [
            ...
            ]
        ],
        'adapter2' => [
            ...
            ]
        ]
    ]
]
];

And my goal is to get the configuration of all my adapters in one instruction. I don't know if it is possible. There is this instruction to get one adapter :

$sm->get('adapter1');

But I want to have something like that:

$sm->get('adapters');

I didn't find any solution right now so I decided to ask the question here... I suppose this is something possible because the file just containing a simple array...

Yours

EDIT :

I tried

$sm->get('config')['db']['adapters'];

But it returns an array of string. Actually, I would like an array of Objects. Objects of Adapter. The same way I get an adapter in this way :

$sm->get('adapter1');

Yours

edigu
  • 9,878
  • 5
  • 57
  • 80
Renaud
  • 11
  • 5
  • 1
    If you just want the config : `$adapters = $sm->get('config')['db']['adapters];`. The `config` service key will return the application's merged configuration array. – AlexP Nov 10 '16 at 21:21
  • Thank you... But I've just see that I don't want an array of string but an array of objects. Objects of Adapter. The same way I get an object with `$sm->get('adapter1');` – Renaud Nov 10 '16 at 22:08
  • Do not put significant additional information in comments: edit your post. Follow [How do I ask a good question?](http://stackoverflow.com/help/how-to-ask). – greybeard Nov 11 '16 at 01:13

2 Answers2

0

Not sure if this is what you are looking for but you could use Zend\Config class for this. You can find more information on this class here in the documentation:

// Create the object-oriented wrapper using the configuration data
$adaptersConfig = $sm->get('config')['db']['adapters'];
$adapters = new \Zend\Config($adaptersConfig);

Now you can access adapters like you wanted:

$adapters->adapter1;
Wilt
  • 41,477
  • 12
  • 152
  • 203
  • Hey, Thank you for you reply. I tried but the result is not the same I want. The new Zend\Config\Config class does not create the object I was expected. I maybe found another solution... I'm working on it. – Renaud Nov 11 '16 at 12:52
  • @Renaud, so what do you expect to get then? Do you want the actual adapters instead of the config for the adapters? – Wilt Nov 11 '16 at 12:55
0

If you want a collection of adapter objects you could model this as a service that you register with the service manager.

This service is simple a collection class, called DbAdapterCollection. Each adapter object is stored and referenced by it's name.

class DbAdapterCollection
{
    protected $adapters = [];

    public function __construct(array $adapters = [])
    {
        $this->setAdapters($adapters);
    }

    public function hasAdapter($name)
    {
        return isset($this->adapters[$name]);
    }

    public function getAdapters()
    {
        return $this->adapters;
    }

    public function setAdapters(array $adapters)
    {
        $this->adapters = [];

        foreach ($adapters as $name => $adapter) {
            $this->setAdapter($name, $adapter);
        }
    }

    public function getAdapter($name)
    {
        if (! $this->hasAdapter($name)) {
            throw new \RuntimeException('An adapter with the name \'' . $name . '\' could not be found.');
        }
        return $this->adapters[$name];
    }

    public function addAdapter($name, \Zend\Db\Adapter $adapter)
    {
        $this->adapters[$name] = $adapter;
    }
}

To populate this class with the adapter objects you can use a service factory to inject them in to the class __construct. We can use the service manager to also load the required config so we know which adapters should be added to the collection service.

class DbAdapterCollectionFactory
{
    public function __invoke(ServiceManager $serviceManager, $name, $requestedName)
    {
        $config  = $serviceManager->get('config');

        $options  = [];
        $adapters = [];

        if (isset($config['my_app']['services'][$requestedName])) {
            $options = $config['my_app']['services'][$requestedName]; 
        }

        if (! empty($options['adapters']) && is_array($options['adapters'])) {
            foreach ($options['adapters'] as $name => $adapter) {
                if (is_string($adapter) && $serviceManager->has($adapter)) {
                    $adapter = $serviceManager->get($adapter);
                }       
                if ($adapter instanceof \Zend\Db\Adapter) {
                    $adapters[$name] = $adapter;
                }
            }
        }

        return new DbAdapterCollection($adapters);
    }
}

The configuration for this example could look like this.

'service_manager' => [
    'factories' => [
        'DbAdapterCollection' => 'MyApp\\Db\\DbAdapterCollectionFactory'
    ],
],

// Example app config
'my_app' => [
    'services' => [
        'DbAdapterCollection' => [
            // adapterName => dbServiceName,
            'adapters' => [ 
                'adapter1' => 'MyApp\\Db\\Adapter1'
                'adapter2' => 'adapter2'
                'adapter3' => 'adapter3'
            ],
        ]
    ],
],

All then you would need is to call the service from the service manager.

$adapterCollection = $serviceManager->get('DbAdapterCollection');
if ($adapterCollection->has('adapter1')) {
    $adapter = $adapterCollection->get('adapter1');
} 
AlexP
  • 9,906
  • 1
  • 24
  • 43
  • Nice way but I found a better appropriate solution. (In the getServiceConfig() method in the Module class, I just add an index which returns an array of my adapters. – Renaud Nov 13 '16 at 09:26