Proxy is one of those words that makes you sound technically smart and it’s seen an increase in usage over the last 20 years according to Google Books Ngram Viewer.

Well what does proxy even mean? Lets take a look in more detail.

Proxy Pattern

The word proxy often means something that replaces something else and behaves similar to the original object. An example of a proxy is when you give the authority to someone to vote on your behalf; it’s called proxy voting.

The proxy pattern in OOP follows a similar concept in that a proxy object stands in place of a real object. That proxy object generally forwards the instuctions on to the real object, but could add additional functionality as needed.

The simplest implementation of a proxy object just uses the magic __call function to dynamically pass along missing methods to the real object:

<?php
class Proxy
{
  public $obj;

  public function __construct($obj)
  {
    $this->obj = $obj;
  }

  public function __call($method, $parameters)
  {
    return $this->obj->{$method}(...$parameters);
  }
}

Well that’s easy enough in PHP. Gotta love that syntactic sugar.

Proxy Pattern in the Wild 🕵️

There are various uses for the proxy pattern. People give examples of lazy loading files to authorizing method calls in proxy objects. Interestingly, I found a place in the Laravel framework that uses the proxy pattern for neither of these purposes.

Remember that time Taylor Otwell wrote about the tap function that was inspired by the same named method in Ruby? Well here is his original post. In it, he describes two ways to use the tap helper function. The first way has 2 arguments:

<?php
tap($object, function ($object) {
    $object->save();
});

The second passes along only 1 argument, then chains a method, and he claims that it returns the original object:

<?php
return tap($user)->update([
    'name' => $name,
    'age' => $age,
]);

I was digging around and found where the tap helper function is defined and this is what the code looks like:

<?php
if (! function_exists('tap')) {
    // Call the given Closure with the given value then return the value.

    function tap($value, $callback = null)
    {
        if (is_null($callback)) {
            return new HigherOrderTapProxy($value);
        }
        $callback($value);
        return $value;
    }
}

So the if block handles when it’s 1 argument and the remaining code handles when there’s 2 arguments. Interesting. So what is this HigherOrderTapProxy that gets returned instead of the original object? Let’s take a look:

<?php
namespace Illuminate\Support;
class HigherOrderTapProxy
{
    public $target;

    public function __construct($target)
    {
        $this->target = $target;
    }

    public function __call($method, $parameters)
    {
        $this->target->{$method}(...$parameters);
        return $this->target;
    }
}

Ahh I see. So this proxy object just intercepts the method call on the object, calls the method with the parameters, but ignores the return value of that method call, and then always returns the “target” aka the original object.

BAM proxy pattern in real life. Definitely did not think I would find one in Laravel that would be easy to understand, but there you have it! Until next time, happy coding!