Slim 3 框架 - 将数据从中间件传递到控制器 - 动作参数

Slim 3 framework - Passing data from middleware to controller - action args

我正在使用带有 slim 3 的 controller/middleware 构建,我想从附加到组的中间件中将一些数据传递到我的控制器 - 操作中的 $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());

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

谢谢。

因此您只需要将数据从中间件传递到控制器

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');
        //...
    }
}

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

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

基本上,如 slim router docs

中所述

The route callback signature is determined by a route strategy. By default, Slim expects route callbacks to accept the request, response, and an array of route placeholder arguments. This is called the RequestResponse strategy. However, you can change the expected route callback signature by simply using a different strategy. As an example, Slim provides an alternative strategy called RequestResponseArgs that accepts request and response, plus each route placeholder as a separate argument. Here is an example of using this alternative strategy; simply replace the foundHandler dependency provided by the default \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);
});

You can provide your own route strategy by implementing the \Slim\Interfaces\InvocationStrategyInterface.

然而,对于将一些标准化数据注入$args[]数组的任务,默认的\Slim\Handlers\Strategies\RequestResponseclass会做它需要的一切减去注入数据。

因此,我简单地扩展了 class:

<?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 视图。

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

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