Generators in PHP 5.5 (with PDO)

As the first alpha of PHP 5.5 has been released, now is a great time to play with its new features. The first new feature is generators. Generators are like very simple iterators.

PDO’s PDOStatement class implements Traversable, which means you can iterate over it with foreach:

$sth = $dbh->prepare("SELECT * FROM users");
$sth->execute();

foreach ($sth as $result) {
	print_r($result);
}

This is great as it abstracts away much of retrieving result sets from a database and gets you straight to an array-like structure. This iterator is great as PDO only retrieves the results as they’re requested, reducing memory usage.

You can recreate this by making a class that implements Iterator and its abstract methods. Whilst this is quite simple, PHP 5.5 brings generators, which allow you to create iterators using a single function.

Here’s an example, using PDO again. First, some boiler plate code to set up:

$dbh = new PDO('sqlite::memory:'); 
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->exec("CREATE TABLE users (
	id INTEGER NOT NULL,
	name VARCHAR(255),
	PRIMARY KEY (id)
)");

$dbh->exec("INSERT INTO users (id, name) VALUES (1, 'tom')");
$dbh->exec("INSERT INTO users (id, name) VALUES (2, 'dick')");
$dbh->exec("INSERT INTO users (id, name) VALUES (3, 'harry')");

$sth = $dbh->prepare("SELECT * FROM users");
$sth->execute();

If we wanted to, we could now iterate over $sth using foreach like so:

foreach ($sth as $result) {
	print_r($result);
}

Instead, lets create a generator that fetches rows from $sth, but passes control back to the foreach:

function fetch($sth, $fetchMode) {
    while ($result = $sth->fetch($fetchMode)) {
        yield $result;
    }
}

The key here is the “yield” keyword, which can be thought of as “start returning an item from an array”. The foreach can then loop through the results like this:

$results = fetch($sth, PDO::FETCH_OBJ);
foreach ($results as $result) {
	echo $result->name . "\n";
}

Whilst this example is a bit pointless (as PDO already provides an Interator), you can see that generators are a simple way of creating iterators.

Enabling and fixing suPHP on Ubuntu

I use suPHP on the VPS that runs this blog as it’s great for performance and security. After updating Ubuntu, suPHP somehow got disabled. Fixing it was a bit of trial and error but in the end this is what worked:

  1. Make sure everything is installed
    sudo apt-get install libapache2-mod-suphp
  2. Edit the end of /etc/suphp/suphp.conf
    [handlers]
    ;Handler for php-scripts
    ;application/x-httpd-suphp="php:/usr/bin/php-cgi"
    application/x-httpd-php="php:/usr/bin/php-cgi"
  3. Edit /etc/apache2/apache2.conf
    suPHP_Engine on
    suPHP_AddHandler application/x-httpd-php .php
  4. Make sure suPHP is enabled and restart Apache
    sudo a2enmod suphp
    sudo service apache2 restart

That should be it.