Adam Innes · Blog

PHP 5.4: Short Arrays, Traits and a Built-in Dev Server

· 3 min · php, web development

PHP 5.4.0 came out on March 1, and it’s the first PHP release in a while that I’d call fun. The release announcement lists new syntax (traits and a shorter way to write arrays), better performance and memory use, a web server built into the command line binary, and a cleanup that removes several deprecated features. That last part is the one that can bite you on upgrade, so it’s worth reading before you flip a server over.

A web server in the CLI

This is the feature I’d try first. Go to a project directory and run this:

$ cd ~/public_html
$ php -S localhost:8000

PHP now serves that directory on port 8000. If a request doesn’t name a file, you get index.php or index.html, and a 404 if neither exists. The -t option points it at a different document root. If you also pass a PHP file, it becomes a router script that runs at the start of every request, and when that script returns false the requested file is served as is. That’s enough to run most front controller setups:

<?php
// router.php
if (preg_match('/\.(?:css|js|png|jpg|gif)$/', $_SERVER['REQUEST_URI'])) {
    return false; // let the server send the static file
}
require __DIR__ . '/index.php';

Start it with php -S localhost:8000 router.php and you have a working dev environment without touching an Apache vhost. The manual page for the built-in web server is clear that it’s a development tool, though, and the 5.4 docs say outright that it should not be used in production. I’d take that at face value. It’s for trying a framework or hacking on a small app on your laptop, not for real traffic.

Short arrays and friends

You can now write [1, 2, 3] or ['name' => 'Adam'] instead of array(...). The old form still works, so there’s no rush to rewrite anything. A few smaller syntax changes came along too. You can index straight into a function’s return value with foo()[0], call a method on a new object with (new Foo)->bar(), write binary literals like 0b1010, and use <?= in templates whether or not short_open_tag is enabled. Closures also support $this now.

Traits

Traits are the bigger idea. PHP has single inheritance, so if two unrelated classes need the same handful of methods you’ve had to pick between copy and paste, a shared base class that doesn’t really make sense, or a helper object. A trait is a bundle of methods you pull into a class with use. You can’t instantiate one on its own.

<?php
trait Loggable {
    protected function log($message) {
        error_log(get_class($this) . ': ' . $message);
    }
}

class InvoiceMailer {
    use Loggable;

    public function send() {
        $this->log('invoice sent');
    }
}

The rules are spelled out in the traits chapter of the manual. Methods defined in the class win over trait methods, which in turn win over inherited ones. When two traits bring in methods with the same name, you resolve it with the new insteadof operator. My advice is to keep traits small and focused. They’re great for little bits of shared behavior and easy to abuse as a way to glue unrelated code into one class.

One upgrade note: trait, callable and insteadof are now reserved words, so a class or function with one of those names will break.

What got removed

This is the part to check before upgrading. Register globals, magic quotes and safe mode are gone, along with their php.ini settings. get_magic_quotes_gpc() still exists but always returns false, so code that strips slashes only when magic quotes are on keeps working. Call-time pass by reference is gone, break and continue no longer take variable arguments, and session_register() and its siblings have been removed.

If an old php.ini still switches on a removed setting like register_globals or safe_mode, PHP 5.4 doesn’t quietly ignore it. The startup code checks for them and raises a core error saying the directive is no longer available, so clean up your ini files first.

Two more things from the 5.3 to 5.4 migration guide caught my eye. PHP no longer guesses your timezone or reads it from the TZ environment variable. If date.timezone isn’t set, it falls back to UTC and issues a warning, so set it explicitly. And the old ext/sqlite extension moved to PECL, while sqlite3 and pdo_sqlite are unaffected.

Should you upgrade?

For new projects, I’d start on 5.4 now. The built-in server alone makes local development nicer. For existing apps, the removals are mostly things that were deprecated for years and that you shouldn’t be relying on anyway, but “shouldn’t” and “don’t” are different things in legacy code. Grep for register_globals, magic_quotes and session_register, set date.timezone, run your tests on 5.4, and the upgrade should be pretty uneventful.

← all posts