Using PHP closures with the observer pattern

January 28, 2013 | Leave a comment

PHP 5.3 introduced the concept of anonymous functions, often called closures. These have been present in languages like JavaScript for a long time, and have been incorporated into PHP as part of its ongoing transformation into a first-class web programming language.

Simply put, they allow you to assign the workings of a function to a variable. For example:

$myFunction = function() {
    return true;
}

This simplifies a lot of common programming tasks. For example, prior to PHP 5.3, you might have used the array_walk function to perform operations on the entities in an array as follows:

function processEntity(&$entity) {
    // perform some action on $entity
}

$myArray = array('one','two','three','foo','bar');

array_walk($myArray, 'processEntity');

Whereas now you can go ahead and perform your entire processing step in one statement:

$myArray = array('one','two','three','foo','bar');

array_walk($myArray, function(&$entity) {
    // perform some action on $entity
});

This works because in PHP, an anonymous function is a callable: it can be included wherever the name of a function was previously requested, without any further modifications to your code.

This is handy in itself for many uses, but it comes into its own when you combine it with the observer pattern. Here, observer methods listen for an event to be triggered, and may alter the subject of the event (where appropriate). I’m a big user of observers: Elgg’s architecture has depended on them since 2004, and in every project I’ve worked on since, observers have been called on system events (for example to run code when an object is saved or updated), and actions (for example to run code when a form action is fired, to log the user on, post some content, or some other action). They allow you to create simple object-based architectures where the components are logically separate but each section can communicate with each other section.

While I used to roll my own observer code, lately I’ve fallen in love with Symfony’s Event Dispatcher component (not least because it does pretty much what I was doing before, with richer functionality and code I don’t have to maintain myself!).

Events and actions are referenced with a unique string. For this example, I’ll use unique.event.name, and attach a listener callable that will be triggered whenever the event is dispatched, as follows:

$eventDispatcher->addListener('unique.event.name', $callable);

(There’s also an optional third parameter, $priority, which is an integer that indicates priority. Higher integers have a higher priority.)

Remember that a callable can be a string containing a function name, an array referencing a class method, or an object with an __invoke method. But because an anonymous function is also a callable, we can stick a function right there in the listener call:

$eventDispatcher->addListener('unique.event.name', function($event) {
    // Do something with $event
});

Invoking the event is as simple as calling:

$eventDispatcher->dispatch('unique.event.name', $event);

$event here is an object of class Symfony\Component\EventDispatcher\Event, so you could make your life easy and create subclasses for different kinds of events that carry payloads of useful data:

class exampleEvent extends Symfony\Component\EventDispatcher\Event {
    public $simplePayload;
    function __construct($simplePayload) {
        $this->simplePayload = $simplePayload;
    }
}

Then you can trigger the event and attach some payload data in one line:

$eventDispatcher->dispatch('unique.event.name', new exampleEvent($someData));

Each listener callable has direct access to this event object, and can modify it in turn. The object also provides access to the event dispatcher via $event->getDispatcher(), which can launch more nested events, or halt propagation to the next listener in the chain.

By creating different subclasses of Event for different event types, you can easily attach special event functionality or payload support for those instances. I can easily imagine defining UserLoginEvent, UserLogoutEvent and UserSaveEvent, for example. Event listeners can then check for event type (if they need to) by checking the class of the event.

By using anonymous functions for this process, you get to keep your listener and logic code in the same place, and write fewer lines of code overall, while making the most of a very powerful software development pattern.

More secure password hashing in PHP 5.5

September 12, 2012 | 1 comment

The most recent set of PHP releases suggest that the core development team are serious about keeping PHP at the forefront of web development technology, and addressing some of its legacy criticisms. I’ve previously talked about the JsonSerializable interface; now, PHP 5.5 is introducing an easier way to make password hashing more secure.

(What is password hashing, and why is it important for protecting your users’ privacy? Here’s a great introduction.)

Here’s the RFC, which was recently accepted. The idea is that too many people are using a naïve salting mechanism plus weak hash algorithm to store their passwords:

$hash = md5($password . $salt);

This is subject to attack on a bunch of different levels. bcrypt is the generally-accepted algorithm for hashing passwords, but the truth is, new attacks emerge all the time, and the standard is going to be a constantly moving target.

The new PHP passwords API will abstract that away. All you’ll do is get a hash like this:

$hash = password_hash($password);

To verify a password, you can simply use:

if (password_verify($password, $hash)) { /* Yay */ } else { /* Uh oh */ }

Salts and algorithms will be taken care of behind the scenes. Should you ever need to re-hash the password, at a point where you have the plain-text password, the password_needs_rehash($hash) function will let you know:

if (password_needs_rehash($hash)) {
    $hash = password_hash($password);
    // update hash in database
}

If you don’t want to have the salts managed transparently for you, and want to set a higher computational cost on the hash algorithm than the default 10, you can specify them in the function options:

password_hash($password, PASSWORD_DEFAULT, array("cost" => 14, "salt" => $salt));

There’s a compatible PHP shim for coders who won’t be using PHP 5.5 for a while yet.

I’m pretty excited about these additions to the PHP APIs. I’m also looking forward to checking out Ratchet, a way to develop real-time applications using WebSockets in PHP – something that removes a long-standing hole in the PHP functionality stack.

Meanwhile, I’m still experimenting with more development-related posts. Again, please let me know if this was useful!

Serializing PHP objects into JSON with JsonSerializable

August 29, 2012 | 3 comments

JSON (JavaScript Object Notation) is a handy data interchange format that’s overtaken XML in a very short time for a lot of API use cases – and rightly so. It’s easy to use, bandwidth efficient, and widely supported across platforms and languages.

PHP is still one of the most widely-used web scripting languages. It’s perhaps not as cool as Python or Ruby on Rails, but it’s got its adherents. I’m still a fan, although there are some things – like long-polling real-time sites – that are much harder to do on the platform. And when it comes to JSON, it doesn’t get any easier than $json_string = json_encode($php_data); and $php_data = json_decode($json_string);. (Assuming you have the PHP JSON module compiled and enabled – but if you’re using PHP 5.2 or above, you probably do.)

Unfortunately, if you’re using object orientated code and your data to encode includes an object, json_encode() has traditionally not been as friendly as it might have been. Sometimes, for example, you want to define exactly how your objects translate to JSON, to avoid lost data (or too much data). This is particularly true if you’re using magic methods to get and set properties, as I often do.

PHP 5.4 contains a new interface, JsonSerializable, that gives you this control. Once you add the interface to your class:

class myClass implements JsonSerializable {
    // ...
}

You can add a new function, jsonSerialize, that will be triggered whenever json_encode() is run on the object, and returns the PHP data of your choice:

class myClass implements JsonSerializable {
    // ...
    
    function jsonSerialize() {
        $data = array();
        // Represent your object using a nested array or stdClass,
        // in the way you want it arranged in your API
        return $data;
    }
}

Now, when you run json_encode() over a data structure that includes your objects, you’ll know that they’re being saved in a way that can easily be interpreted by your API consumers. Again, the function should return PHP data that can be serialized by json_encode(), rather than encoded JSON data. I recommend using nested arrays, or a stdClass object, for simplicity.

Note that unlike, say, serialize() (which serializes data in a PHP-specific format), this isn’t a two-way translation. In other words, json_decode() won’t automatically reconstitute your object with class from your data.

We can illustrate that by taking the following test class (which I’ll expand first and then print the var_export() output for):

class TestClass {
    public $foo = 'bar';
    public $dev = 'null';
}
 
TestClass::__set_state(array( 'foo' => 'bar', 'dev' => 'null', ))

Which json_encode() encodes as:

{"foo":"bar","dev":"null"}

(Because that was a simple object, there was no need to employ jsonSerialize() in its construction.)

In turn, the JSON string is decoded back into PHP as:

stdClass::__set_state(array( 'foo' => 'bar', 'dev' => 'null', ))

Note that the classname has vanished and the class is reduced to being a stdClass. As a result, you need to take care when consuming JSON data and turning it back into your internal data structures – which is a very good idea anyway. It’s perhaps worth creating your own validator function that can take in a stdClass object and, following sanity checking and sanitization, turn it back into one of your own classes.

And that’s it. I don’t normally write about code here, so please let me know if you found this useful.

Bonita: a PHP template manager with lofty ambitions

August 23, 2011 | Leave a comment

I’m fed up of using the same PHP template pattern over and over in my web apps, so I decided to write it from scratch and iterate on some core ideas. And then open source it under an Apache 2.0 license.

The result is Bonita: a simple PHP templating engine. It’s definitely version 0.1, but I thought I’d put it out there now in the spirit of release early, release often. Future enhancements will include a static cache, simple functions to handle action tokens for XSS, and some stubs to do things like semi-automatically generate RSS and Activity Streams.

Isn’t PHP already a template language? Yes and no. Its origins are definitely as a template language, but these days it’s a perfectly good way to write fully-fledged web applications. After all, Drupal, WordPress, StatusNet and Elgg are all PHP-based. (Yes, the language is much-maligned, and certainly has its flaws, but it’s also much-used.)

Aren’t there already templating systems for PHP? Yes, but they’re typically designed for sites rather than apps. Bonita includes support for creating streams and automatically drawing PHP objects out of the box, as well as content post-processing and template plugins. Support for anti-XSS form action tokens is another example of a feature that really mostly makes sense for web app developers.

Why are you releasing this? By releasing this under an Apache 2.0 license, I get to continue using the ideas, but I also get to share it, and let the wider community help me build out the system. That seems like a more efficient model for development to me; it also sits better with me. (And, hey, if nobody uses it, the worst that’s happened is that I have a great backup of my code on GitHub.)

Are you releasing Bonita on behalf of anyone? No. This is my own code, and it’s not being released or endorsed by any other organization or entity.

Interested? Bonita’s GitHub project is over here.

Next Page »