Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

PHP 5.4 by examples

DZone's Guide to

PHP 5.4 by examples

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

Aren't you already tired of listing PHP 5.4 features to colleagues and having to demonstrate them? In this article I'll include all the code samples you need to make them get a feel for the new use cases.

Arrays

Let's start with something not invasive and nice to look at: array syntax similar to JSON's.
$colors = [
    'blue' => '#0000FF',
    'red'  => '#FF0000',
];
$otherColors = array(
    'blue' => '#0000FF',
    'red'  => '#FF0000',
);
var_dump($colors === $otherColors); // true
Not only creating arrays is less verbose, but it's now possible to dereference closures and callables as array elements and call them directly, without an temporary variable.
$dereferenceMe = array(
    'echo' => function ($value) { echo $value, "\n"; }
);
$dereferenceMe['echo']('Hello World');

Binding

Here is a bank account object containing a method that builds a closure. While ordinary variables must be cited in the *use* clause to be referenced inside the closure, $this is automatically bound to the object creating it.
class BankAccount
{
    private $name;

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

    public function newLoan($anotherBankAccount)
    {
        return function() use ($anotherBankAccount)
        {
            echo "$this->name loans money to $anotherBankAccount\n";
        };
    }
}

$bank = new BankAccount('Bank');
$loan = $bank->newLoan('Paperino');
$loan();
Here's something slightly more evil to do: picking the same closure and rebinding it to another BankAccount object.
$paperone = new BankAccount('Zio Paperone');
$anotherLoan = $loan->bindTo($paperone);
$anotherLoan();

This use case may still be acceptable as you can access the private properties of the same class where the closure is created, and the code is kept in a single place. The practical effect is that you can still move and rename properties by only looking at the class's source file for reference.

Here's instead something much more evil to do:

class Car
{
    private $name;

    public function __construct($name)
    {
        $this->name = $name;
    }
}
$car = new Car('A Ferrari');
$yetAnotherLoan = $loan->bindTo($car, $car);
$yetAnotherLoan();
A simple way to access any private property or method of any object.

Callables

There is now a specific type hint for callable constructs, like anonymous functions, string representing function names, array($object, 'methodName') and so on.
class Page
{
    public function display(callable $c)
    {
        echo $c(), "\n";
    }
}

$page = new Page();
$page->display(function() { return 'Hello'; });
All the callable structures conform to the type hint and can be... called directly, even in the array($object, 'methodName') form:
class Person
{
    public function greeting() { return 'Hello'; }
}
$person = new Person;
$page->display(array($person, 'greeting'));

function function_greeting()
{
    return 'Hello';
}
$page->display('function_greeting');

Fluent instantiation

You can now call methods directly on a new statement, providing a more fluent interface in case the object needs some further configuration afyter construction:
class EmptyHtmlTag
{
    public function __construct($name)
    {
        $this->name = $name;
    }

    public function display()
    {
        return "<{$this->name} />\n";
    }
}
echo (new EmptyHtmlTag('hr'))->display();
Moreover, method names can refer not only to variables but also to many computable constructs, like an access to an array element:
$methods = array(
    'display'
);
$tag = new EmptyHtmlTag('hr');
echo $tag->{$methods[0]}();

JSON

Objects can easily be passed to json_encode() by implementing a new interface:
class Car implements JSONSerializable
{
    public function __construct($model)
    {
        $this->model = $model;
    }

    public function jsonSerialize()
    {
        return array('model' => $this->model, 'type' => 'car');
    }
}

echo json_encode(new Car('Ferrari')), "\n";

The server

php -S localhost:8000
will launch a small HTTP server for development needs, targeting the current directory as document root. It won't serve a list of files like other embeddable servers, so include an index.php script if necessary.

Traits

Traits are a mechanism for multiple inheritance or for copying and pasting code automatically code, mixing in different templates to build a new class.
trait Versioned
{
    private $version = 1;

    public function newVersion()
    {
        $this->version++;
    }

    public function getVersion()
    {
        return $this->version;
    }
}

trait HasAName
{
    private $name;

    public function getName()
    {
        return $this->name;
    }
}

class User
{
    use Versioned, HasAName;

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

$me = new User('Giorgio');
$me->newVersion();
echo $me->getName(), "\n";
echo $me->getVersion(), "\n";
Inheritance hierarchies of 3 or 4 levels are already a stretch due to testability and little cohesion of the leaf classes, so be careful not to extend this endless hierarchies also in the horizontal direction:
trait HasADescription { use HasAName; /* ... */ }
class SuperUser extends User { use HasADescription; /* ... */ }

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}