Я хочу подключиться к другой базе данных по URL. Я пытаюсь установить атрибут запроса и получить этот атрибут в *Factory.php
,
Я редактирую autoload/pipeline.php
:
<?php
$app->pipe(UrlHelperMiddleware::class);
$app->pipe(\App\Action\Choose::class);
$app->pipeDispatchMiddleware();
в Choose.php
Я реализую process()
как это:
<?php
public function process(ServerRequestInterface $request, DelegateInterface $delegate)
{
/** @var RouteResult $route */
$route = $request->getAttribute(RouteResult::class);
if ($route->getMatchedRouteName() == 'FirstRoute' or $route->getMatchedRouteName() == 'SecondRoute') {
$request = $request->withAttribute('DB_NAME', $route->getMatchedParams()['param']);
}
return $delegate->process($request);
}
Основная проблема заключается в *Factory.php
У меня нет доступа к запросу.
Любая попытка доступа к Interop\Http\ServerMiddleware\MiddlewareInterface
или же Psr\Http\Message\ServerRequestInterface
в * Factory.php возникает такая же ошибка.
Есть ли способ передать параметр из промежуточного программного обеспечения конвейера в фабричный класс?
Если вы используете Zend-ServiceManager, вы можете попробовать это (просто теория, не проверенная):
Создайте 2 фабрики базы данных в вашей конфигурации:
'db.connection.a' => DbFactoryA::class,
'db.connection.b' => DbFactoryB::class,
Затем в зависимости от маршрута, в Choose
Вы загружаете необходимое соединение и передаете его в контейнер как соединение по умолчанию.
$db = $container->get('db.connection.a');
$container->setService('db.connection.default', $db);
И теперь во всех следующих промежуточных программах вы можете получить соединение по умолчанию.
ОБНОВИТЬ:
Как упоминалось в комментариях, для этого требуется вставить контейнер, что считается плохой практикой. Как насчет того, чтобы обернуть их в общий класс соединения и установить требуемый из Choose
:
class Connection
{
private $connection;
/**
* @var ConnectionInterface
*/
private $db_a;
/**
* @var ConnectionInterface
*/
private $db_b;
public function __construct(ConnectionInterface $a, ConnectionInterface $b)
{
$this->db_a = $a;
$this->db_b = $b;
}
public function setConnection($connection)
{
if ($connection === 'a') {
$this->connection = $this->db_a;
return;
}
$this->connection = $this->db_b;
}
public function getConnection()
{
return $this->connection;
}
}
Или вы можете внедрить только конфигурацию и создать соединение с базой данных, которое действительно необходимо. Сохраните его в свойстве для кэширования (как это делает контейнер).
Других решений пока нет …