Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

JarekTkaczyk's avatar

Different response content type?

I wonder how you guys handle api-like requests in such scenario:

  1. app responds to simple requests with html (simple page refresh)
  2. app responds also to ajax calls that load content without refresh, but still with html (no frontend framework in use, simple old-school ajax content loading)
  3. sometimes it needs to respond with raw json data

Now, assuming every call to the same endpoint/url requires the same data and just different output format, I wonder what is the best way to handle such requests:

  1. Separate stack (controllers, middleware etc) for each type
  2. Separate stack for html and json types and returned html content based on ajax/non-ajax request
  3. one to rule them all and just differentiate the response, depending on accept header

Thanks for all your opinions guys, @bashy @usman @pmall your thoughts appreciated as well.


I asked about terminable middleware as well, but apparently it was wrong by definition, since that middlewares are called after the request was sent.

0 likes
8 replies
4jZW7jVSdS4U6PC's avatar

If I understand this you want to filter between something like

mysite.com/users which shows the view

mysite.com/user.json which shows the json list

Right? (if yes maybe I have a solution)

JarekTkaczyk's avatar

@pmall That's what I think as well (one for all) and I'm playing with terminable middleware, that's why I'm asking. However I want to make it adhere to SRP too, and that's where I have to think it over.

@ludo237 Not really through the url .json suffix, but rather htttp accept header. But please, share your solution.

pmall's avatar

What is not SRP in my solution ?

JarekTkaczyk's avatar

@pmall Did I say that? :)

What I'm a bit worried about is that api calls may sometimes in fact require a bit different response, not only without html wrapper. Not referring to your solution again, I didn't analyze it thoroughly yet, just had a look previously.

pmall's avatar

i'm curious to see what you come up with

1 like
JarekTkaczyk's avatar

@pmall Something based on your macro. Right now I'm looking for a way to dynamically extend View object with layout template, like @extends does.

Any idea about it?

usman's avatar

@JarekTkaczyk thank you for including me in the list of the legends :) . But, I am kind of in the same boat as you here. Currently working on a simple content sharing application that allows users like: add links to content, comments and votes and things like that. For handling ajax calls it uses same routes as for non-ajax calls and return the html in both cases ( and some messages in case of ajax ) . On the client site I am completely relying on the Http status codes for error handling to keep the json response simple for example this is what I have inside the Base Controller :

abstract class Controller extends BaseController {

    use ValidatesRequests;

    /**
     * layout to be used with this controller
     * @var string
     */
    protected $layout = '';

    /**
     * creates a json representation of the view
     * @param  string $view
     * @param  array $viewData
     * @return JsonResponse
     */
    protected function jsonResponse($view = null, $viewData = [], $mergeData = [])
    {   
        $jsonData = [];

        if($view)
        {
            $jsonData['html'] = view($view,$viewData)->render();

            if(($data = array_shift($viewData)) instanceof Paginator)
            {
                $jsonData['next_page_url'] = $data->nextPageUrl();//for infinite scroll and load more functionality.
            }
        }

        //merging any extra data to the final JSON response.
        //this may include success and error messages.
        $jsonData = array_merge($jsonData,$mergeData);

        return new JsonResponse($jsonData);
    }

    /**
     * creates the view response for the controller
     * @param  string $view
     * @param  array $viewData
     * @param  array $layoutData
     * @return Response
     */
    protected function viewResponse($view, $viewData = [], $layoutData = [])
    {
        if($this->layout)
        {
            return view($this->layout, $layoutData)->nest('content',$view, $viewData);
        }

        return view($view,$viewData);
    }

}

And a sample controller action for updating or deleting a posted link to some content looks like this: ( the app is not over-engineered)

    /**
     * saves the updated record
     * @param  Request $request
     * @return Response
     */
    public function processEditLinkForm(LinkFormRequest $request)
    {
        $link = $this->link->findOrFail($request->id);
        $link->update($request->only('url','title','description'));

        if($request->ajax())
        {
            return $this->jsonResponse('link.link',compact('link'),[
                'message' => 'Link updated successfully!'
                ]);
        }
        //here redirect back otherwise.
    }
    /**
     * deletes the link record from database
     * @param  Request $request
     * @return Response
     */
    public function deleteLink(LinkFormRequest $request)
    {
        $this->link->findOrFail($request->id)->delete();

        if($request->ajax())
        {
            return $this->jsonResponse(null,[],[
                'message'=>'Link Deleted successfully!'
                ]);
        }
    //redirect back otherwise
    }

In case of ajax call my responses would look like this:

{   
    html: "<...........> .....</>",
    message: "usually a success message for crud success"
}
//or as simple as:
{ message: "deleted successfully!" }

I am still looking for a better solution.

Usman.

1 like

Please or to participate in this conversation.