Request/response customization

Hi!

I’m pretty new in slim framework and after working years with “company-made” products that doesn’t really follow norms and standards, i am a little bit lost trying to do something :

I’m looking for a way to implement new request (ServerRequestInterface) and responses (ResponseInterface) objects, just to add some custom codes, for example :
a $request->trygetparam or trypostparam that would check if there is a param for a key given, and if not maybe throw an error.
a “return $response->setJsonPayload($array)” that would do the work to json encode the array, put the header on the response and so on.

I know how i could do all of that with like a class with static function that would manipulate the request/response objects but i would really like to make the elements available on the objects themselves. Having my api class be like :

public function details(MyCustomRequest $request, MyCustomReponse $response){
 $id = null;
  if($request->tryGetParam("", $id)){
    return   $response->setJsonPayload(["id"=>$id]);
  }
 return $response->error(403, "missing param");
}

I hope i’m not asking too much (or too stupid).
Thanks in advance.

Welcome @captainatwork

First you should note that Slim uses the PSR-7 standard for HTTP request and response objects. This means they are “immutable”. So every change the request/response headers must return a new (cloned) object. Second, my concern is that your approach does not comply with the PSR-7 standard and would make it later much harder to maintain.

If you are still sure to implement such an approach, you may take a look at the slim/http project on Github. This package provides some decorators for the HTTP request and response objects.

as someone that went the “custom” request / response route. (and had a fight with odan :stuck_out_tongue: ) i can safely say… dont bother with custom request / response. it WILL make your life harder (ive gone back to “mostly” vanilla slim as it really really just works)

what i now use instead is a middleware that sets up the “parameters” onto the normal $request->getAttribute()

// TODO: sanitize the inputs
        foreach ((array)$request->getQueryParams() as $key => $value) {
            $request = $request->withAttribute("GET." . $key, $value);
        }
        foreach ((array)$request->getParsedBody() as $key => $value) {
            $request = $request->withAttribute("POST." . $key, $value);
        }

        foreach ((array)$route->getArguments() as $key => $value) {
            $request = $request->withAttribute("PARAM." . $key, $value);
        }

then usage in the controller is simply $request->getAttribute("POST.name");

also this might be of some use to you as well

as for the response…

go with something like

use System\Responders\Responder;
class JobsController {
    function __construct(
        protected Responder $responder,
    ) { }

    public function __invoke(Request $request, Response $response): Response {

    	// ...

    	return $this->responder->withResponse(
            response: $response,
            data: $data,
            errors: $errors,
        );
    }
}

this lets you use your container (php-di?) in the responder as well. gives you a TON of extra options for a few bits of extra boiler plate. but it makes it super easy to switch our responders then

slim middleware is super super super strong.

1 Like

thanks both of you for your answers. @odan was on point with slim/http which was basically what i was looking for, without need for me to implement a new one.

i understand that i may lose a little bit of PSR-compatibility but for the sake of simplicity for my team and myself i think it’s a fair trade to have a little bit of easy-to-use decorators (especially because, the way i managed to use it, it’s really localized to specific controllers, and doesn’t damage the framework itself). so i went with it and it worked really well.

but anyway, thanks again, and thanks to slimPHP for existing, it’s by far the simplest, and (for lack of a better term) “cutest” framework out there.

1 Like