【问题标题】:Slim 3 framework - Passing data from middleware to controller - action argsSlim 3 框架 - 将数据从中间件传递到控制器 - 动作参数
【发布时间】:2019-07-13 13:11:06
【问题描述】:

我正在使用带有 slim 3 的控制器/中间件构建,我希望从附加到组的中间件中将一些数据传递给我的控制器中的 $args 参数 - 操作。

这里有一些代码:

class MyController
{
    protected $container;

    public function __construct(ContainerInterface $container) {
        $this->container = $container;
    }

    public function index(Request $request, Response $response, $args) {
        return $this->container->get('renderer')->render($response, "index.html.twig", $args);
    }
}
class MyMiddleware
{
    public function __invoke(Request $request, Response $response, $next)
    {
// do some stuff to inject further down to $args some data
        return $next($request, $response);
    }
}
$app->group('/group', function () use ($app){
//routes
    })->add(new MyMiddleware());

我的用例是将内容发送到由这些控制器的操作呈现的所有视图,所以我也可以通过其他方式执行此操作:)

谢谢。

【问题讨论】:

    标签: php controller action middleware slim-3


    【解决方案1】:

    所以您只需将数据从中间件传递到控制器

    怎么样

    class MyMiddleware
    {
        public function __invoke(Request $request, Response $response, $next)
        {
            $request = $request->withAttribute('myMagicArgument', 42);
            return $next($request, $response);
        }
    }
    

    然后在控制器中

    class MyController
    {
        //...
        public function index(Request $request, Response $response) {
            $yourAttributeFromMiddleware = $request->getAttribute('myMagicArgument');
            //...
        }
    }
    

    【讨论】:

    • 我知道这一点......但基本上我需要添加到该控制器中的每个操作 $yourAttributeFromMiddleware = $request->getAttribute('myMagicArgument');并返回 $this->container->get('renderer')->render($response, "index.html.twig", array_merge($args, $yourAttributeFromMiddleware));
    • 使用我提出的解决方案 + 然后查看 InvocationStrategyInterface 并实施您自己的 Invocation 策略,该策略将从 Request 收集数据并将该魔术值作为 Args 参数的一部分传递给您(基本上您需要使用您的自定义实现 \Slim\Handlers\Strategies\RequestResponseArgs ) - 基本上你会在 InvocationStrategyInterface 实现中执行 array_merge :)
    • 啊哈....不知道这一点。我会尝试一下,看看效果如何 :) 谢谢你的想法。
    • 谢谢,它有效 :) 为我如何使用它添加一些信息:我添加了一个 MyRequestResponse extends RequestResponseArgs 类,该类在 __invoke 方法中执行操作,然后在容器中执行操作:$container['foundHandler' ] = function ($container){ return new MyRequestResponse(); };
    【解决方案2】:

    为了完整起见,我将扩展@jDolba 给出的出色答案

    不幸的是,尽管它让我朝着正确的方向前进,但仍然需要进行一些实验才能让一切正常运行。

    基本上,如slim router docs中所述

    路由回调签名由路由策略决定。经过 默认情况下,Slim 期望路由回调接受请求、响应、 和一组路由占位符参数。这被称为 请求响应策略。但是,您可以更改预期路线 通过简单地使用不同的策略来回调签名。作为一个 例如,Slim 提供了一种替代策略,称为 RequestResponseArgs 接受请求和响应,加上每个路由 占位符作为单独的参数。这是一个使用这个的例子 替代策略;只需替换 foundHandler 依赖项 默认提供\Slim\Container

    $c = new \Slim\Container();
    $c['foundHandler'] = function() {
        return new \Slim\Handlers\Strategies\RequestResponseArgs();
    };
    
    $app = new \Slim\App($c);
    $app->get('/hello/{name}', function ($request, $response, $name) {
        return $response->write($name);
    });
    

    您可以通过实施 \Slim\Interfaces\InvocationStrategyInterface.

    然而,对于将一些标准化数据注入$args[] 数组的任务,默认的\Slim\Handlers\Strategies\RequestResponse 类会完成它所需的一切,而不是注入数据。

    因此,我只是扩展了该类:

    <?php
    
    namespace MyProject\Handlers\Strategies;
    
    use Psr\Http\Message\ResponseInterface;
    use Psr\Http\Message\ServerRequestInterface;
    
    use \Slim\Handlers\Strategies\RequestResponse;
    
    class SomeNewInvocationStrategy extends RequestResponse
    {
        /**
         * Invoke a route callable.
         *
         * @param callable               $callable The callable to invoke using the strategy.
         * @param ServerRequestInterface $request The request object.
         * @param ResponseInterface      $response The response object.
         * @param array                  $routeArguments The route's placholder arguments
         *
         * @return ResponseInterface|string The response from the callable.
         */
        public function __invoke( callable $callable, ServerRequestInterface $request, ResponseInterface $response, array $routeArguments)
        {
            $routeArguments['test'] = 'testing testing 123';
            return parent::__invoke( $callable, $request, $response, $routeArguments );
        }
    } 
    

    我的容器声明如下所示:

    <?php
    
    use Slim\App;
    
    return function (App $app) {
        $container = $app->getContainer();
    
        $container['foundHandler'] = function() {
            return new MyProject\Handlers\Strategies\SomeNewInvocationStrategy();
        };
    }
    

    然后在我的所有控制器操作中,我都可以访问$args['test']。此外,这可以直接传递到任何 Twig 视图。

    这对于访问控制之类的任务很有用,在这些任务中我总是想在处理请求之前加载用户的角色,但我相信它还会有许多其他用例。

    我希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-09-10
      • 2018-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-15
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      相关资源
      最近更新 更多