PHP 5.4 by examples
Join the DZone community and get the full member experience.
Join For FreeAren'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); // trueNot 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:8000will 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; /* ... */ }
PHP
Opinions expressed by DZone contributors are their own.
Trending
-
5 Key Concepts for MQTT Broker in Sparkplug Specification
-
Best Practices for Securing Infrastructure as Code (Iac) In the DevOps SDLC
-
Which Is Better for IoT: Azure RTOS or FreeRTOS?
-
Comparing Cloud Hosting vs. Self Hosting
Comments