Busy trying this approach out as i wanted a way to “trigger” an error so wanted to do it on the $response (but trying to take in as much as you guys have said as possible). So now with the responder pattern for response instead of decorator as per akrabat’s suggestion.
Dow does everyone solve the “different output types” thing? As in “if the query string has a ?format=json
” then output the content as json (just the “data”). How i did it previously was to setup a custom method(s) on the response object to set a template and data on its object then with a middleware. If those are set to work out what the desired output should be then output it as that format. (data and template are still separate so this is possible, the middleware then sets the body on the response).
With responder that moves into the responder object. but the responder needs access to the request to be able to decide what it needs to output. so either its a
// using container di stuff
return $this->responder($request,$response,template,data);
or its a
$responder = new Responder($request,$response);
return $responder->render(template,data)
The 2nd option seems a bit more preferential except when it comes to adding in container deps like loggers, templater etc in which case the constructor might get a bit big.
motivation:
My application front ends use the same routes as the ajax routes. So if you for instance go to /page in a normal window it will render the pages data and template together and hand you the content as html. If you click an ajax button in the page to “reload content” then it will hit the page with a XMLHttpRequest
in which case it outputs just the pages data as json. (You can also override the behavior by specifying type - defaults to html). - Im very reluctant to have separate routes for json (ajax) vs html.
Part of the issue i face is that this needs to work for errors as well. So the error handler will basically set a template (if the error is in html) and data array for json. So the new Responder() way seems to be a viable option since i can easily implement that, but the error handler doesnt have a request / response as the routes have.
So i can either “decide” on content type in the route handler, or in a middleware. The middleware way seems preferential to me but my route still needs to return a ResponseInterface object (i could duplicate the methods and return a ResponseInterface type with my responder).
opdan’s responder passes the $response object into the ->withTemplate(response,template,data) method, but if for instance i wanted to “respond with an error” as in ->error(404,“page cant be found”), using slims internal throw new \Slim\Exception\HttpNotFoundException($request, "page cant be found");
requires the $request. Or if i need to interrogate the request to figure out in what format i need to pass the data back as i’ll need the request.
Im sure others have elegant solutions to these problems im facing. Care to share?