У меня есть эти модели-классы:
МастерМодель:
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 один адаптер)
Как я могу это сделать? Есть ли другой способ получить конфигурацию?

Чтобы ваша фабрика была вызвана, вам необходимо использовать 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 был примером. Ключевым моментом является то, что вы используете фабрику для создания своего класса. Везде, где у вас есть доступ к Service Manager, вы можете использовать его для создания своего класса, вызвав $ sm-> get (\ sf \ ZfCommons \ Model \ MasterModel :: class). На фабрике, реализующей FactoryInterface, Service Manager поставляется как $ container.
Чтобы ответить на ваш второй вопрос, это зависит от того, что вы пытаетесь сделать. Как правило, вам не нужно хранить ServiceManager в своем классе, а лучше создавать свой класс, вводя в него то, что вам нужно. Как и в приведенном мною примере, фабрика создает экземпляр объекта вашего класса. Фабрика при вызове конструктора вашего класса может внедрить все, что вам нужно, включая ServiceManager ($ container), если вы хотите. Проверьте Документы Service Manager и связанные методы внедрения зависимостей
если я правильно понял, мои занятия в порядке. но я должен создать SomethingFactory, чтобы он работал? второе решение (ZF имеет встроенную абстрактную фабрику адаптера БД) выглядит лучше. Как я могу получить переменную $ container в модели или другом классе?