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

ottopilot's avatar

Issues Extending Response Facade in Laravel 5.2

To return a json formatted response, normally at the end of each controller method I do something like:

return response()->json($data);

I have standardized a response message format in json tjhat I send to the browser. To avoid exposing the structure of the response to every method of every controller I've created a helper class of sorts. The methods in this class are designed to support method chaining so the intent is to allow controllers to call something like:

return response()->setDataJson($data)->redirect('url')->notify('message')->send();

Behind the scenes each of these methods help construct an array with various default values and the send() method basically just calls Laravel's Reponse facade json() method to convert the array to json.

While prototyping I got this working by simply instantiating my custom response class in my controller's constructor like this (notice I pass a ResponseFactory instance to the constructor)...

$this->response = new MyResponse(response());

and then changing how I access the response by doing this:

return $this->response->setDataJson($data)->redirect('url')->notify('message')->send();

Of course this work so my class is doing what it's supposed to do. The problem is this seems kind of hackey and I want to use the original syntax above "response()->set...." To do this I assumed that I would have to create a Facade, or more appropriately, extend the stock Laravel Response facade.

Toward that end I followed this technique:

http://slashnode.com/new-response-types-laravel-using-custom-facades/

Everything seems like it's provisioned correctly and yet I get "BadCallMethodExceptions" related to the first custom method in my class I attempt to call (setDataJson). The only obvious difference between my implementation and the referenced one is that my methods are not declared static, but I can't see why that should matter. I'm simply extending a class and PHP places no such restrictions on the method declaration.

Does anyone have a better reference on how to extend Laravel Facades (other than paid videos)?

0 likes
11 replies
ejdelmonico's avatar

What do you mean by extending facades? Facades are just a proxy for an underlying implementation in the service container...in other words a proxied shortcut to mainly make code more readable. I don't see why you would want to extend a specific Facade. If you want to create a custom facade so that an implementation is proxied in the service container, that sounds like it could be useful. But, that's just my opinion.

ottopilot's avatar

I believe that what I'm doing is essentially creating a custom facade. I just used the word "extend" because that's essentially what I'm doing at the class level. But I did attempt to replace the stock Response facade:

\Illuminate\Support\Facades\Response::class

with my custom Response facade:

\App\Facades\Response::class

in app.php's aliases array. I think that qualifies as a "new" facade.

What I'm trying to do is make a custom response class that extends the functionality of the stock Laravel response handler. I want to be able to use the same syntax of the stock response() method, but chain methods I have implemented in a custom class to format the data as desired.

Laravel appears to be complaining that it can't find my custom methods, which implies that I'm still somehow calling the stock Response facade, yet I did comment it out in app.php (and call "composer dump-autoload" for good measure). Unfortunately my knowledge of the underpinnings of Laravel is limited so I don't know if Laravel imposes some kind of special requirement on extending the Response class.

ejdelmonico's avatar

Well, that is a tough one because basically, Laravel uses Traits and Interfaces in a great deal of the code. You could tract down the trait that is used and make a helper class using the ResponseFactory. Just guessing here.

ottopilot's avatar

I have to be careful about mocking stuff I don't fully understand, but honestly it should not be this difficult to extend the framework. I appreciate your effort. I'm going to stick with what works for now and then investigate another implementation later.

clay's avatar

Here's what I've done i'n the past. I'm not sure if this is exactly what you're looking for and there's probably a better way, but it worked for me:

I created a class MyResponse that extends Illuminate\Routing\ResponseFactory. In the constructor, I call the parent constructor, passing in the needed Illuminate\Routing\Redirector and Illuminate\Contracts\View\Factory. Then I added my custom methods to the class. In a service provider, I bound my class to the string respond, then created a custom facade and added it to my config. Finally, I could just use Response; in my controllers and have access through the facade to all of my custom methods as well as the methods of the ResponseFactory class. See below:

// MyResponse.php
<?php

namespace App;

use Illuminate\Routing\Redirector;
use Illuminate\Routing\ResponseFactory;
use Illuminate\Contracts\View\Factory as ViewFactory;

class MyResponse extends ResponseFactory
{
    public function __construct(ViewFactory $viewFactory, Redirector $redirector)
    {
        parent::__construct($viewFactory, $redirector);
    }

    public function myMethod()
    {
        dd('Handling it');
    }
}
//custom facade
<?php

namespace App;

use Illuminate\Support\Facades\Facade;

class MyResponseFacade extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'respond';
    }
}

// in a serviceprovider
    public function register()
    {
        $this->app->bind('respond', function($app){
            return new \App\MyResponse($app['Illuminate\Contracts\View\Factory'], $app['redirect']);
        });
    }
// in config/app
// in aliases, change the Response line to 
'Response' => 'App\MyResponseFacade',
// in a controller
use Response;

// ...
return Response::view('test.test');
//or
return Response::myMethod();
//or
return Response::json(['message' => 'This is my message'], 200);

Also, you could overwrite the 'response' helper

function response($content = '', $status = 200, array $headers = array())
    {
        $factory = app('respond');
        if (func_num_args() === 0)
        {
            return $factory;
        }
        return $factory->make($content, $status, $headers);
    }
1 like
dde911's avatar

@clay @clay @clay Hi Clay, Your code helps me a lot. I follow you until this step :

// in a serviceprovider public function register() { $this->app->bind('respond', function($app){ return new \App\MyResponse($app['Illuminate\Contracts\View\Factory'], $app['redirect']); }); }

To my knowledge, there is no ServiceProvider for the Response. Where did you add this registry part ?

dde911's avatar

PS: How do you have your code so well formatted on Laracasts ? Is there an help to format a reply ?

dde911's avatar

Test ​ Based on : laracasts.com/discuss/channels/code-review/how-to-write-code-in-laracast

dde911's avatar

So until this part:

// in a serviceprovider
    public function register()
    {
        $this->app->bind('respond', function($app){
            return new \App\MyResponse($app['Illuminate\Contracts\View\Factory'], $app['redirect']);
        });
    }
ottopilot's avatar

Hadn't thought about extending the ResponseFactory. Perhaps that will work.

I'm still confused why it seems in every example of extending the ResponseFactory or a Facade that the methods added must be declared static. That obviously precludes chaining unless I get an instance like:

$result = TestClass::getInstance () ->toValue(5) ->add(3) ->subtract(2) ->add(8) ->result();

In any case, I'll try to integrate your example and see what happens. Thanks for taking the time to respond, clay.

Please or to participate in this conversation.