Quickshiftin - Clever Crazy Code

Passing ‘pointers’ to private methods in PHP

September 28th, 2015

If  you’re writing any code with Javascript, you’re surely familiar with the concept of a callback. Turns out callbacks have been available in PHP for a long time too, they just haven’t been first class citizens for as long. What’s really neat though, is with the advent of the Closure class in PHP 5.3 you can now pass callbacks to private methods!

The early days and the ‘psuedo-type’ callback

Long ago in a galaxy far far away… Actually in PHP < 5, there was already such a thing called the ‘psuedo-type’ callback. This basically meant you could pass a specially formed array or string around as a rough pointer to a function. The array or string could be passed to call_user_func or call_user_func_array. This worked with classes and objects. Let’s look at a quick example

// Define an arbitrary class
class A
{
    public function doStuff()
    {
        echo "I'm working hard boss!\n";
    }
}

// Instantiate the class and call doStuff via a 'pointer'
$a        = new A();
$callable = [$a, 'doStuff'];
call_user_func($callable); // I'm working hard boss!

Callbacks between objects

In this example we’re creating a callable to an already instantiated class. This is very straightforward; however sometimes you’ll see classes pass a reference to $this to some code it calls. While it introduces coupling, the technique is used to implement various design patterns, such as  Observer and State patterns. Essentially one object needs another object to help it along in some way, but that helper object may need to ask the main object to take care of some things on its own, thus it must ‘call back’ to the main object.

A real example for callbacks

Recently I’ve been working on a project that makes API calls to Magento and runs image manipulation via the Imagick extension. These are both time consuming operations and the application user is stuck waiting a while for them to run. What I needed was a way to have the helper classes pass status updates to the frontend, but I didn’t want to have them call echo. That’s because I wanted to maintain a clean separation of concerns and these classes have nothing to do with outputting information to the end user. What’s more I don’t want to clutter up those classes with any knowledge of whether they’re being run via the command line or the browser. On the next page we’ll look at mock implementations of this system and how PHP has evolved to support clean interfaces with private callbacks!