我想根据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
我无法访问请求
尝试访问* Factory.php中的Interop\Http\ServerMiddleware\MiddlewareInterface
或Psr\Http\Message\ServerRequestInterface
会产生同样的错误。
有没有办法将参数从管道中间件传递到工厂类?
答案 0 :(得分:0)
如果您使用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;
}
}
或者您只能注入配置并创建真正需要的数据库连接。将其存储在属性中以进行缓存(就像容器一样)。