Route and Middleware Strategies

Hello !

Currently I using Container Resolution on my Controllers and I was able to “extend” the Routing Strategy by modifying RequestResponse.php.

Code Example:

/**
 * Default route callback strategy with route parameters as an array of arguments.
 */
class RequestResponse implements InvocationStrategyInterface
{
    /**
     * Invoke a route callable with request, response, and all route parameters
     * as an array of arguments.
     *
     * @param array|callable         $callable
     * @param ServerRequestInterface $request
     * @param ResponseInterface      $response
     * @param array                  $routeArguments
     *
     * @return mixed
     */
    public function __invoke(
        callable $callable,
        ServerRequestInterface $request,
        ResponseInterface $response,
        array $routeArguments
    ) {
        foreach ($routeArguments as $k => $v) {
            $request = $request->withAttribute($k, $v);
        }

        ---------------------------- HERE IS THE CHANGE!!! ------------------------

        if (!$callable instanceof Closure && $callable[0] instanceof BaseController) {
            
            $controller = $callable[0];

            $controller($request, $response, $routeArguments);
        }

   ---------------------------- END OF CHANGE ------------------------

        return call_user_func($callable, $request, $response, $routeArguments);
    }

The idea behind this is to my Controller process all Slim Data ( Using my Parsers ) and to give my ControllerBase more control over the PSR Objects beforehand. ( Give me thoughts about this or if this is a bad practise at all )

Its a simple trick to pass the PSR objects and arguments directly to my Controller, instead of calling in each method of the class parent__invoke(); and keep the normal call to the method.

Example of this usage:

// Route Controller Classes extends from BaseController.
// This could be also registerUser(){} without the PSR Objects.
// return Slim Response Object
function registerUser(Request $request, Response $response, Array $args){
    // Method from my Controller that returns a formated type of data using Request Body for my own purposes.
    $data = this->getRequestBody();

    return $this->getResponse();
}

The thing is that Middlewares does not follow this RequestResponse Strategy and I would like to do the same to my Middlewares ( Yes I use a MiddlewareController ).

At the moment I have to call parent__invoke(request,response) at the top of my middleware method.

Example:

// Middlewares classes extends from BaseController
function middleware(Request $request, Response $response){

     // Don't wanna call that.
    // parent__invoke($request,$response);

   // Do Stuffs....

}

I would like to understand where the Strategy is invoked so I can learn how to extend Middlewares functionality to my purposes.

Thanks in Advance,
LosLobos.

Slim`s Invocation Strategy is only used for the route callable.

So Slim will execute: App Level Middlewares -> Route Level Middlewares -> and then use the Strategy to invoke your Route Callable

1 Like

I looked up the code and this line that you marked up caught my attention.

/** @var InvocationStrategyInterface $handler */
$handler = isset($this->container) ? $this->container->get(‘foundHandler’) : new RequestResponse();

I’m adding these changes directly to Slim but this line suggests that I can use the Container to override the current InvocationStrategyInterface, is this correct ?

Can I just write my own InvocationStrategy that implements InvocationStrategyInterface and on the app initialization insert on Container my own Handler ?

Also this doesn’t change the way that Middlewares are executed right ? If I would like to make Slim execute my Middleware’s invoke method, how I would do that ?

Yes!

Yes!

Yes, won’t change.
There is no easy way to do it but if you want you will need to implement your own MiddlewareAwareTrait (Probably change this line)
Then extends App and Route to use your MiddleWareAwareTrait
As you had to change Route you will have to extends Router and reimplement createRoute() to use your own Route Then inject your new Router on Dependency Container(Like the Invocation Strategy)

You can see the Services on Container here

1 Like

Thanks for the help !

Now I can handle myself here. I was not aware of the Services on Container ( I checked the docs a long time ago, maybe it wasn’t there ).

I’ll implement my own MiddlewareAwareTrait to make it work. Hope on Slim 4 there’ll be an easier way to do that. ( Altought is not that hard doing it ).

The help was very much appreciated.

Thanks,
LosLobos.