简体   繁体   English

在zend expressive 2中将参数从管道中间件传递到工厂类

[英]pass parameter from pipeline middleware to factory class in zend expressive 2

I want to connect to different database according to URL. 我想根据URL连接到其他数据库。 I try to set request attribute and get that attribute in *Factory.php . 我尝试设置请求属性并在*Factory.php获取该属性。
I edit autoload/pipeline.php : 我编辑autoload/pipeline.php

<?php
$app->pipe(UrlHelperMiddleware::class);
$app->pipe(\App\Action\Choose::class);
$app->pipeDispatchMiddleware();

in Choose.php I implement process() like this: 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);
}

The main problem is in *Factory.php I don't access to request. 主要问题是在*Factory.php我无法访问请求。
Any try to access to Interop\\Http\\ServerMiddleware\\MiddlewareInterface or Psr\\Http\\Message\\ServerRequestInterface in *Factory.php raises same error. 任何尝试访问* Factory.php中的Interop\\Http\\ServerMiddleware\\MiddlewareInterfacePsr\\Http\\Message\\ServerRequestInterface尝试都会产生相同的错误。

Is there any way pass parameter from pipeline middleware to factory class? 有什么方法可以将参数从管道中间件传递给工厂类?

If you use zend-servicemanager you can try this (just a theory, not tested): 如果您使用zend-servicemanager,则可以尝试以下操作(只是一个理论,未经测试):

Create 2 database factories in your config: 'db.connection.a' => DbFactoryA::class, 'db.connection.b' => DbFactoryB::class, 在您的配置中创建2个数据库工厂: 'db.connection.a' => DbFactoryA::class, 'db.connection.b' => DbFactoryB::class,

Then depending on the route, in Choose you load the connection you need and pass it to the container as the default connection. 然后根据路由,在Choose加载所需的连接,并将其作为默认连接传递到容器。 $db = $container->get('db.connection.a'); $container->setService('db.connection.default', $db);

And now in all following middleware you can grab the default connection. 现在,在以下所有中间件中,您都可以获取默认连接。

UPDATE: 更新:

As mentioned in the comments, this requires the container to be injected which is considered bad practice. 如评论中所提到的,这要求注入容器,这被认为是不好的做法。 How about you wrap the two in a common connection class and set the required from Choose : 您如何将两者包装在一个通用的连接类中,并从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;
    }
}

Or you can inject only the config and create the database connection that's really needed. 或者,您可以只注入配置并创建真正需要的数据库连接。 Store it in a property for caching (like the container does). 将其存储在用于缓存的属性中(就像容器一样)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM