Laravel Internals: Proxy pattern with the ForwardsCalls trait

Sometimes it’s good to put PHP’s magic methods to use. One such magic method is __call which allows for virtual methods to be called on an object. This also helps with the Proxy pattern where one object might accept another object via the first class’ constructor to then proxy all subsequent missing method calls to the second object.

One of Laravel’s internal traits actually makes this process a lot simpler. We can implement by just creating a class with the ForwardsCalls trait. Then we add our own __call function to the class with will pass the object we’re proxying, the name and the parameters to the forwardCallTo.

As you can see this example works nicely to allow use to forward and calls to the object. You might wonder though, why can’t we just use the call_user_func function?

Well you could but the problem with this comes when you then make a mistake calling a method that does not exist on the target object. See below:

As you can see the message is a bit vague and non descript. We get a TypeError instead of a clearly defined exception. We could just apply a call directly to the object, maybe that would work better?

This is ok but we’re getting a PHP error instead of an exception, as well as only getting a message about the Target class instead of the Proxy class. That still requires us to remember that the Proxy class is being used.

Now let's see what happens when we use the ForwardsCalls trait instead.

That’s right we now get a far nicer BadMethodCallException which tells us the Proxy class that failed with an undefined method so we don’t have to look into the stack trace to know which class does not have that method.

Conclusion

Often it’s the case Laravel has a hidden treasure or two like this within it’s code. While the impact of this one is minimal, it’s always something to keep in mind as part of the developer experience. If you had a message like the one provided from call_user_func upon a missing method call, how would you debug it when it’s occuring in a production environment? How obvious would it be to track down the cause of the error? Little traits like ForwardsCalls can save a lot of time and headaches for you in the future.

I’m Peter Fox, a software developer in the UK who works with Laravel among other things. Thank you for reading my article, I’ve got several more on both medium and dev.to. If you want to know more about me, head over to https://www.peterfox.me. I’m also now also Sponsorable on GitHub. If you’d like to encourage me to write more articles like this please do consider dropping a small one off donation.

30