Среда Slim 3 — передача данных из промежуточного программного обеспечения в контроллер — аргументы действия

Я использую сборку контроллера/промежуточного программного обеспечения с тонким 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());

Мой вариант использования - отправлять вещи во все представления, отображаемые действиями этих контроллеров, поэтому я также согласен с другими способами сделать это :)

Спасибо.


person C Apetrei    schedule 13.07.2019    source источник


Ответы (2)


поэтому вам нужно просто передать данные из промежуточного программного обеспечения в контроллер

как насчет

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');
        //...
    }
}
person jDolba    schedule 22.07.2019
comment
я знаю об этом... но в основном мне нужно добавить к каждому действию в этом контроллере $yourAttributeFromMiddleware = $request->getAttribute('myMagicArgument'); и вернуть $this-›container-›get('renderer')-›render($response, index.html.twig, array_merge($args, $yourAttributeFromMiddleware)); - person C Apetrei; 24.07.2019
comment
используйте мое предложенное решение + затем посмотрите на InvocationStrategyInterface и реализуйте свою собственную стратегию вызова, которая будет собирать данные из запроса и передавать вам это магическое значение из запроса как часть параметра Args (в основном вам нужно использовать свою собственную реализацию \Slim \Handlers\Strategies\RequestResponseArgs ) - в основном вы будете делать это array_merge в реализации InvocationStrategyInterface :) - person jDolba; 25.07.2019
comment
Ага.... не знал об этом. Попробую, а там как получится :) Спасибо за идею. - person C Apetrei; 27.07.2019
comment
Спасибо, это работает :) Чтобы добавить некоторую информацию о том, как я его использовал: я добавил класс MyRequestResponse extends RequestResponseArgs, который делает что-то в методе __invoke, а затем в контейнере: $container['foundHandler'] = function ($container){ вернуть новый MyRequestResponse(); }; - person C Apetrei; 27.07.2019

Для полноты я собираюсь расширить отличный ответ, данный @jDolba

К сожалению, хотя это и заставило меня двигаться в правильном направлении, все же потребовалось немного экспериментов, чтобы все заработало.

По сути, как описано в документации по тонкому маршрутизатору.

Сигнатура обратного вызова маршрута определяется стратегией маршрута. По умолчанию Slim ожидает, что обратные вызовы маршрута будут принимать запрос, ответ и массив аргументов-заполнителей маршрута. Это называется стратегией RequestResponse. Однако вы можете изменить ожидаемую сигнатуру обратного вызова маршрута, просто используя другую стратегию. Например, 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.

Это полезно для таких задач, как контроль доступа, когда я всегда хочу загружать роли пользователей перед обработкой запроса, но я уверен, что для этого будет много других вариантов использования.

Надеюсь, это кому-нибудь поможет.

person DazBaldwin    schedule 09.08.2019