Вызов класса модели Zend Framework 3 для получения конфигурации базы данных

У меня есть эти модели-классы:

МастерМодель:

namespace sf\ZfCommons\Model;

use Zend\Db\Sql\Sql;
use Zend\Db\Adapter\Adapter;

class MasterModel extends AbstractModel
{
    public $db;
    public $dbSys;
    public $dbUserClient;
    public $dbSysParams;
    public $dbUserClientParams;

    public function __construct()
    {
        $this->dbSys = new Adapter(Array(
            'driver' => 'Pdo_Mysql',
            'hostname' => 'localhost',
            'database' => 'db1',
            'username' => 'root',
            'password' => 'password',
            'charset' => 'utf8'
            ));

        $this->dbUserClient = new Adapter(Array(
            'driver' => 'Pdo_Mysql',
            'hostname' => 'localhost',
            'database' => 'db2',
            'username' => 'root',
            'password' => 'password',
            'charset' => 'utf8'
            ));

        if ($this::TBL_PLACE == 'user_client') {
            $this->db = $this->dbUserClient;
        } else {
            $this->db = $this->dbSys;
        }
        $this->sql = new Sql($this->db);
    }
}

Абстрактная модель:

namespace sf\ZfCommons\Model;

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

class AbstractModel
{
    /**
     * @var ServiceManager
     */
    protected $serviceManager;

    /**
     * @return ServiceManager
     */
    public function getServiceManager()
    {
        return $this->serviceManager;
    }

    /**
     * @param mixed $serviceManager
     * @return $this
     */
    public function setServiceManager(ContainerInterface $serviceManager)
    {
        $this->serviceManager = $serviceManager;
        return $this;
    }
}

ModelFactory:

namespace sf\ZfCommons\Model;

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

class ModelFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        echo "############# ModelFactory #################";

        $service = (null === $options) ? new $requestedName : new $requestedName($options);

        return $service->setServiceManager($container);
    }
}

В моем module.config.php есть строки:

...
'service_manager' => [
        'factories' => [
            \sf\ZfCommons\Model\MasterModel::class => \sf\ZfCommons\Model\ModelFactory::class
        ],
        'invokables' => [
        ],
    ],
...

Но Завод не называется ... Что здесь не так? Я хочу прочитать параметры db1 и db2 из конфигурации и установить 2 адаптера (для каждого db один адаптер)

Как я могу это сделать? Есть ли другой способ получить конфигурацию?

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
0
0
326
1

Ответы 1

Чтобы ваша фабрика была вызвана, вам необходимо использовать Service Manager, чтобы получить сервис MasterModel там, где вам нужно ее использовать, например, на другой фабрике. Например:

class SomethingFactory implements FactoryInterface
{
   public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
   { 
     $masterModel = $container->get(\sf\ZfCommons\Model\MasterModel::class);
     // then do something with $masterModel, like inject it into something else
     return new Something($masterModel);
   }
}

Кроме того, ZF имеет встроенную абстрактную фабрику адаптеров БД, которая может создавать для вас оба адаптера без необходимости создавать класс MasterModel и его фабрику. Предполагается, что вы создаете приложение MVC.

В ваш config/autoload/local.php или config/autoload/global.php добавьте следующее:

'db' => [
    'adapters' => [
        'dbSys' => [
            'charset' => 'utf8',
            'database' => 'db1',
            'driver' => 'Pdo_Mysql',
            'username' => 'username',
            'password' => 'password',
            'hostname' => 'localhost',
        ],
        'dbClient' => [
            'charset' => 'utf8',
            'database' => 'db2',
            'driver' => 'Pdo_Mysql',
            'username' => 'username',
            'password' => 'password',
            'hostname' => 'localhost',
        ],
    ],
],

В вашем module.config.php (хотя было бы лучше поместить это в config/autoload/global.php) вы можете добавить следующие строки:

...
'service_manager' => [
     'factories' => [
         'dbSys' => \Zend\Db\Adapter\AdapterAbstractServiceFactory::class,
         'dbClient' => \Zend\Db\Adapter\AdapterAbstractServiceFactory::class,
     ],
     'invokables' => [
     ],
 ],
...

Но вам все равно нужно использовать Service Manager в какой-то момент, чтобы получить адаптеры. Используя приведенный выше пример:

$dbSys = $container->get('dbSys);
$dbClient = $container->get('dbClient');

Надеюсь это поможет.

если я правильно понял, мои занятия в порядке. но я должен создать SomethingFactory, чтобы он работал? второе решение (ZF имеет встроенную абстрактную фабрику адаптера БД) выглядит лучше. Как я могу получить переменную $ container в модели или другом классе?

db1975 30.05.2018 10:11

SomethingFactory был примером. Ключевым моментом является то, что вы используете фабрику для создания своего класса. Везде, где у вас есть доступ к Service Manager, вы можете использовать его для создания своего класса, вызвав $ sm-> get (\ sf \ ZfCommons \ Model \ MasterModel :: class). На фабрике, реализующей FactoryInterface, Service Manager поставляется как $ container.

Eric Richer 30.05.2018 15:03

Чтобы ответить на ваш второй вопрос, это зависит от того, что вы пытаетесь сделать. Как правило, вам не нужно хранить ServiceManager в своем классе, а лучше создавать свой класс, вводя в него то, что вам нужно. Как и в приведенном мною примере, фабрика создает экземпляр объекта вашего класса. Фабрика при вызове конструктора вашего класса может внедрить все, что вам нужно, включая ServiceManager ($ container), если вы хотите. Проверьте Документы Service Manager и связанные методы внедрения зависимостей

Eric Richer 30.05.2018 15:14

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