Over a million developers have joined DZone.

PHP 5.4 by examples

· Web Dev Zone

Start coding today to experience the powerful engine that drives data application’s development, brought to you in partnership with Qlik.

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; /* ... */ }

Create data driven applications in Qlik’s free and easy to use coding environment, brought to you in partnership with Qlik.

Topics:

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

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

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

{{ parent.tldr }}

{{ parent.urlSource.name }}