如何获取数据库适配器的配置

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

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;

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');
}