1

Hi Folks i upgrading my slim framework from slim 2 to slim 4 for older project
for one route i added the one value before route using slim 2 slim.before in index.php

example code:

$app->hook('slim.before', function () use ($app) {
    $env = $app->environment();
    $path = $env['PATH_INFO'];
    
    // spliting the route and adding the dynamic value  to the route
    $uriArray = explode('/', $path);
    $dynamicvalue = 'value';
    if(array_key_exists($uriArray[1], array)) {
        $dynamicvalue = $uriArray[1];
        //we are trimming the api route
        $path_trimmed = substr($path, strlen($dynamicvalue) + 1); 
        $env['PATH_INFO'] = $path_trimmed;
    }
  
});

i read about the add beforemiddleware but cannot able find correct way to add it and i cannot able to find the replacement for $app->environment();

i want to append the dynamic value directly to route

for example

i have one route like this

https://api.fakedata.com/fakeid

by using the above route splitting code i appending the value route using slim.before in slim 2

for example take the dynamic value as test

the route will be

https://api.fakedata.com/test/fakeid

the response of the both api will be same we want to just add value to the route

can any one help me how to do with slim 4

Dinesh s
  • 313
  • 4
  • 19
  • The line `if(array_key_exists($uriArray[1], array))` has a syntax error. Please fix that and give an example of what you expect to be in the `$path_trimmed`. As I understand, you want to have two different routes that return the same result, correct? – Nima Jan 13 '22 at 05:13
  • Exactly , i have a multiple when i add the value `test` in the any route it should return a same response , when we hit the api without keyword test the response should be same – Dinesh s Jan 13 '22 at 05:18
  • Do you also need to know what that specific word is? Or you only want to return same response and don't care about the word itself? – Nima Jan 13 '22 at 05:44
  • i also need to know what is the word is , or can you help me with both the approach with know specific keyword and not know the keyword that will help me for further reference – Dinesh s Jan 13 '22 at 05:50
  • @Nima any other further clarification needed? – Dinesh s Jan 13 '22 at 06:21
  • Is this required for one route only or every route defined in your app? – Nima Jan 13 '22 at 06:27
  • for every route – Dinesh s Jan 13 '22 at 06:50
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/241023/discussion-between-nima-and-dinesh-karthik). – Nima Jan 13 '22 at 06:58
  • for me chat room is not responding – Dinesh s Jan 13 '22 at 07:14

1 Answers1

2

I assume you need to and PATH_INFO to the environment so you can later refer to it in the route callback. You can add a middleware to add attributes to the $request the route callback receives:

use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Response;

class PathInfoMiddleware {
    public function __invoke(Request $request, RequestHandler $handler) : Response {
        $info = 'some value, path_trimmed for example...'; // this could be whatever you need it to be
        $request = $request->withAttribute('PATH_INFO', $info);
        return $handler->handle($request);
    }
}

// Add middleware to all routes
$app->add(PathInfoMiddleware::class);

// Use the attribute in a route
$app->get('/pathinfo', function(Request $request, Response $response){
    $response->getBody()->write($request->getAttribute('PATH_INFO'));
    return $response;
});

Now visiting /pathinfo gives the following output:

some value, path_trimmed for example...

Nima
  • 3,309
  • 6
  • 27
  • 44
  • This is the way. Using environment variables is like passing function parameters through globals: A bad idea. I seem to dimly remember that you can also just declare a handler method to take a `string $PATH_INFO` and Slim automatically figures out from the method signature that it needs the according attribute from the request object. That said, `withAttribute()` creates a new request object, the existing one is immutable. This is essentially the so-called Decorator Pattern. – Ulrich Eckhardt Jan 12 '22 at 20:48
  • 1
    Yes, request and response objects are immutable, that's why one needs to capture the newly created request object. Slim documentation mentions PHP-DI a couple of times so I assume that's the library many developers choose. The feature you are referring to is called autowiring[https://php-di.org/doc/autowiring.html] in PHP-DI, and it uses reflection (it relies on parameter _types_) to figure out how to resolve dependencies. I guess it won't be possible for the library to resolve primitive types (string in this case) without any help. – Nima Jan 12 '22 at 22:39
  • @Nima Thanks for the response , i want to add the value to the route directly instead of returning response to body i re edited the question with full example , and also added the comment for `path_trimmed` value for better clarification ,can you help me with the code to add the value to route directly using middleware – Dinesh s Jan 13 '22 at 05:09
  • @Dineshkarthik Please note, I wrote the value of that attribute to the response body only to demonstrate that it is accessible in the route callback. You can apply your logic on route (as you have access to it in the middleware) and adjust that attribute value accordingly. – Nima Jan 13 '22 at 08:51
  • @Nima Understood but small doubt how we can call this middlware in all route what to add this getAttribute in all the routes `$response->getBody()->write($request->getAttribute('PATH_INFO'));` – Dinesh s Jan 13 '22 at 10:13
  • The line `$app->add(PathInfoMiddleware::class);` attaches the middleware to every route. You have access to `'PATH_INFO'` attribute just like you had access to `$env['PATH_INFO']`. Did you run the code and try to apply your own logic? – Nima Jan 13 '22 at 17:52