Ввести адаптер БД в маппер

Я весьма озадачен тем, как внедрить (Zend/Apigility) в класс маппера конкретный адаптер БД (здесь он называется музыка) в отношении следующего маппера:

AlbumMapper.php

<?php
namespace music\V1\Rest\Album;

use Zend\Db\Sql\Select;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Paginator\Adapter\DbSelect;

class AlbumMapper
{
    protected $adapter;
    public function __construct(AdapterInterface $adapter)
    {
        $this->adapter = $adapter;
    }

    public function fetchAll()
    {
        $select = new Select('album');
        $paginatorAdapter = new DbSelect($select, $this->adapter);
        $collection = new AlbumCollection($paginatorAdapter);
        return $collection;
    }

    public function fetchOne($id)
    {
        $sql = 'SELECT * FROM album WHERE id = ?';
        $resultset = $this->adapter->query($sql, array($id));
        $data = $resultset->toArray();
        if (!$data) {
            return false;
        }

        $entity = new AlbumEntity();
        $entity->exchangeArray($data[0]);
        return $entity;
    }
}

module.php

public function getServiceConfig()
{
    return array(
        'factories' => array(
            'music\V1\Rest\Album\AlbumMapper' =>  function ($sm) {
                $adapter = $sm->get('Zend\Db\Adapter\Adapter');
                return new \music\V1\Rest\Album\AlbumMapper($adapter);
            },
        ),
    );
}

AlbumResourceFactory.php

<?php
namespace music\V1\Rest\Album;

class AlbumResourceFactory
{
    public function __invoke($services)
    {
        $mapper = $services->get('music\V1\Rest\Album\AlbumMapper');
        return new AlbumResource($mapper);
    }
}

Это приведет к получению учетных данных адаптера БД из файла config/autoload/user.global.php, который в соответствии с этим комментарием к файлу не подходит для продуктивного режима.

2 ответа

Вы можете сделать это другим (рекомендуемым) способом с Zend\Db\Adapter\AdapterServiceFactory,

Сначала настройте глобальные настройки БД в config/autoload/global.php и настроить использование AdapterServiceFactory

return array(
     'db' => array(
         'driver'         => 'Pdo',
         'dsn'            => 'mysql:dbname=music;host=localhost',
         'driver_options' => array(
             PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''
         ),
     ),
     'service_manager' => array(
         'factories' => array(
             'Zend\Db\Adapter\Adapter'
                     => 'Zend\Db\Adapter\AdapterServiceFactory',
         ),
     ),
 );

Затем вы можете переопределить некоторые настройки (например, учетные данные БД) в config/autoload/local.php

return array(
     'db' => array(
         'username' => 'root',
         'password' => 'myPassword',
     ),
);

После этого в вашем Module.php Вы могли бы просто получить 'Zend\Db\Adapter\Adapter' от ServiceManager:

public function getServiceConfig()
{    
    return array(
        'factories' => array(
            'music\V1\Rest\Album\AlbumMapper' =>  function ($sm) {
                $adapter = $sm->get('Zend\Db\Adapter\Adapter');
                return new \music\V1\Rest\Album\AlbumMapper($adapter);
            },
        ),
    );
}

Решение, которое я считаю правильным, заключается в редактировании файла Module.php:

public function getServiceConfig()
{
    $dbParams = array(
        'database'  => 'music',
        'username'  => 'root',
        'password'  => 'myPassword',
        'hostname'  => 'localhost',
    );

    return array(
        'factories' => array(
            'music\V1\Rest\Album\AlbumMapper' =>  function ($sm) use ($dbParams) {
                $adapter = new \Zend\Db\Adapter\Adapter(array(
                    'driver'    => 'pdo',
                    'dsn'       => 'mysql:dbname='.$dbParams['database'].';host='.$dbParams['hostname'],
                    'database'  => $dbParams['database'],
                    'username'  => $dbParams['username'],
                    'password'  => $dbParams['password'],
                    'hostname'  => $dbParams['hostname'],
                ));
                return new \music\V1\Rest\Album\AlbumMapper($adapter);
            },
        ),
    );
}

Если есть лучшее решение, я открыт для предложений, но это работает.

Другие вопросы по тегам