01/23/09

New features of PHP 5.3

by Guilherme Blanco

Almost every PHP developer is tracking the changes that will be present in the next release of the language.
For those who have not been tracking the changes, or who have lost track of them – I am here to expose to you everything that PHP 5.3.0 is going to make possible.

The 5.3 release of PHP is the most important release ever, and adds a lot of new features – leading to a delay in its release date. We will look at the most important feature enhancements from version 5.2 to version 5.3.

Let’s first look at the enhancements from PHP 5.1.X to PHP 5.2.0:

  • Memory optimizations
  • Filter extension
  • JSON extension
  • ZIP extension
  • File upload progress hooks
  • DateTime and DateTimeZone objects
  • A couple of others small ones

While these changes were interesting, (especially the first one, which lead PHP 5 to run quicker than PHP 4), they were not very visible and “hype” changes.
Now, let’s take a look at what PHP 5.3 will offer, and let’s try to judge the extent of the upgrade.

PCRE, Reflection and SPL functions are always enabled
It sounds obvious, but some libraries rely on Reflection/SPL to be able to work. One example is Doctrine ORM, which enables you to work at the OO level when using databases as storage medium.
PCRE is a faster library than POSIX RegEx, which may help you to write faster code when dealing with regular expressions.
Also, I am helping with the re-implementation of the spl_object_hash function, to solve some collisions and also to improve performance.

NOWDOC and HEREDOC syntax
While HEREDOC syntax has been available for quite a while, it has some interesting optimizations that will allow it to behave as fast as a normal string declaration. HEREDOC uses the same syntax as a normal string declaration with double-quotes.

$author = 'Guilherme Blanco';

$msg = <<< EOT
This is \x41 message from $author!
EOT;

$msg2 = "This is A message from $author!";

// $msg1 === $msg2
echo $msg1; // Prints: This is A message from Guilherme Blanco!

NOWDOC is a new inclusion to the language, which behaves exactly like a normal string declaration with single-quotes. This means it doesn’t convert the variables and symbol codes to their correspondent values.

$author = 'Guilherme Blanco';

$msg = <<< 'EOT'
This is \x41 message from $author!
EOT;

$msg2 = "This is A message from $author!";

// $msg1 !== $msg2
echo $msg1; // Prints: This is \x41 message from $author!

?: operator
Quick alias for those that have to do this all the time:

// PHP < 5.3.0
$data = isset($var) ? $var : 'default';

// PHP >= 5.3.0
$data = isset($var) ?: 'default';

__DIR__ constant and error modes E_USER_DEPRECATED, E_DEPRECATED
These two error modes are quite simple. They have been introduced to inform the user of stuff being scheduled for removal in future PHP versions.

The __DIR__ constant is a nifty feature for those who are not happy with include paths.
For many years, I personally had to work around directory mismatches by checking the directory of the current file.

Now we’ll be able to use this new constant (which is much faster):

// PHP < 5.3.0
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'File.php';

// PHP >= 5.3.0
require_once __DIR__ . DIRECTORY_SEPARATOR . 'File.php';

__callStatic(), __invoke() and dynamic access to static members
One awesome feature that PHP 5 introduced was the magic methods: __set, __get, __call were quite useful for developers who wanted to control access to their objects. But one missing feature was the ability to control static method calls. To fix that, PHP 5.3 will introduce the __callStatic magic method, which will allow it to handle static method calls, like Foo::bar();

With a new implementation of lambdas and closures that I’ll detail later, more dynamic behaviour will be required from the OO side. To make us – PHP developers – more comfortable, PHP 5.3 will introduce the possibility to call an instance of a class as a function. This support was included under the magic method __invoke(). Sounds weird, but I’ll show you a quick example:

class Foo
{
public function __construct()
{
echo "Calling from constructor...\n";
}

public function __invoke()
{
echo "Calling from invoke...\n";
}
}

$foo = new Foo(); // Prints: Calling from constructor...
$foo(); // Prints: Calling from invoke...

For those who do not know hebrew, the PAAMAYIM NEKUDOTAYIM is not more difficult to be found. Now it’ll be possible to do some weird calls such as $var::staticMethod(); and it’ll work!

Garbage Collector
After a lot of discussion and a Google Summer of Code project, David Wang devised a very good garbage collection mechanism that deals perfectly with cyclical references for PHP.
This means that PHP will use MUCH LESS resources on the server, consuming much less memory, not throwing memory exhausted exceptions any more when importing things.

This extension is built-in, and as far as I have been able to determine, it cannot be disabled. The only way to prevent the Garbage Collector from collecting lost cyclical references, is by calling gc_disable. The other gc_* functions will always be available. This means that you will be able to enable/disable GC through functions gc_enable(), gc_disable(). When it becomes necessary to remove non-referenced objects, simply call gc_collect_cycles(), and PHP will perform its magic for your server.

Late Static Binding
Currently, static references to the current class, like self or __CLASS__ are resolved using the class in which the function belongs, as in where it was defined:

// PHP < 5.3
class A
{
public static function who()
{
echo __CLASS__;
}

public static function test()
{
self::who();
}
}

class B extends A
{
public static function who()
{
echo __CLASS__;
}
}

B::test(); // A

Static references to the current class like self:: or __CLASS__ are resolved using the class in which the function belongs, as in where it was defined, so when we call the test() method on class B it will call the who() method of class A.

LSB tries to solve that problem by introducing a keyword that references the class that was initially called at runtime. Basically, a keyword that would allow you to reference B from test() in the previous example.

It was decided not to introduce a new keyword but rather use “static”, which was already reserved.

// PHP >= 5.3
class A
{
public static function who()
{
echo __CLASS__;
}

public static function test()
{
static::who();
}
}

class B extends A
{
public static function who()
{
echo __CLASS__;
}
}

B::test(); // B

Some people describe static:: as the $this-> resolution for static calls, this is not true as $this-> follows the rules of inheritance while static:: doesn’t.

Namespaces
After months of discussions and a lot of issues that had to be fixed, the namespaces implementation has finally been incorporated, and is already available under alpha 3.
The namespace separator doesn’t please everyone especially those that do not use english keyboard layouts. These people will suffer due to the lack of “\” char on keyboard.

Here is an example usage of this new feature of PHP 5.3:

// File1.php
namespace Foo;

class Bar
{
public function test()
{
try {
do_some_stuf();
} catch (Exception $e) { // Refers to Foo\Exception
// Special handling of Foo Exception
} catch (\Exception $e) { // Refers to PHP Exception
// Special handling of Exception
}
}
}

// File2.php
$b = new Foo\Bar();
$b->test();

// OR...

use Foo\Bar as Baz;

$b = new Baz();
$b->test();

Lambdas Functions/Closures
This can be considered to be an important new feature of PHP, as important as namespace support.

From now on, it’ll be possible to do this:

$func = function ($str) { echo $str; }

$func('Hello World!'); // Prints: Hello World!

Certain situations arose where variables from an outer scope should be allowed internally too. That was a limitation of PHP (variable scope), but it was fixed by the usage of new syntax when defining the lambda function:

$first = "Guilherme";
$second = "Blanco";

$func = function () use (&$first, $second)
{
$first = "Hello";
$second = "World";

echo $first . ' ' . $second; // Prints: Hello World
};

$func();

echo $first . ' ' . $second; // Prints: Hello Blanco

New SPL classes
A lot of work has been done, especially by Etienne on SPL (the Standard PHP Libraries). There is a bunch of new data structures that will be available to users starting on PHP 5.3.
Until now, no updated documentation has been made available, but looking at the source it is easy to figure out how to use these new structure.
Here are the new data structures which will become available:

  • SplObjectStorage (added ArrayAccess support + new features)
  • SplDoublyLinkedList
  • SplStack
  • SplQueue
  • FilesystemIterator
  • GlobIterator
  • SplHeap
  • SplMinHeap
  • SplMaxHeap
  • SplPriorityQueue
  • SplFixedArray
  • RecursiveTreeIterator
  • MultipleIterator



mysqlnd
This is a replacement library (and it’s not an extension) for libmysql, offering a lot of advantages over it the latter. While libmysql was developed primarily for C and C++, mysqlnd is optimized for PHP, taking advantage of the Zend Engine.

These advantages are:

  • Tight integration with Zend Engine
  • Faster execution
  • Lower memory
  • Easier compilation of PHP,since it’s native now (libmysql was bundled with MySQL Server)
  • Usage of PHP stream API
  • Statistical Data Collection
  • Client-side (PHP userland) Query Cache
  • License compatibility
  • Easy to introduce future improvements (prepared statement cache, built-in profiling, automatic load balancing, etc)


Fileinfo
This great PECL extension is now enabled by default in PHP to replace mime_magic.
It is possible to pick the right content-type of files, giving you more secure code and preventing some security issues the previous library allowed, such as uploading a PHP script as a GIF file for example.

Here is a piece of code that shows how to use this extension:

$fileinfo = new finfo(FILEINFO_MIME);
echo $fileinfo->file('/path/to/file/to/be/checked.jpg'); // Prints: image/jpg
$fileinfo->close();

Phar
How do you share your library? How do you share all the source code?
While other languages provide a nifty packaging system, PHP until now had not features to support anything like this.
With PHP 5.3, phar has been included for all of us.

You may not be aware of this – but I work on my spare time on the Doctrine ORM project. Let’s use Doctrine as an example.

First we want to pack our entire project into a single file called “doctrine.phar”.

$phar = new Phar('doctrine.phar', 0, 'doctrine.phar');
$phar->buildFromDirectory('/path/to/doctrine/lib');
$phar->setStub($phar->createDefaultStub('Doctrine.php', 'Doctrine.php'));

It’ll generate a “doctrine.phar” file that we can distribute to people.

Once you have the phar file, you would have to do the following to load the library:

include '/path/to/doctrine.phar';

Improved Windows support
As a member of the PHP Windows team, I cannot finish this article without mentioning that some PHP developers are working extremely hard to be able to provide a lot of *NIX only features for Windows server too.
Two days ago Pierre finished the link() support, which creates symbolic links (shortcuts for Windows users) through PHP. Currently there is a list of functions for which support on Windows is planned – this list can be accessed via URL: http://wiki.php.net/internals/windows/todo

Also, I worked on a PHP webpage at http://windows.php.net which provides customized Windows builds of PHP. It’s possible to pick a snapshot or a VC9 compiled version.

I hope you all enjoy it! =)

Related posts:

  1. Iterating with SPL 101: Directory Iterators
  2. PHPT: Writing tests for PHP
  3. Media encoding with ffmpeg
  4. SPL: The hidden gem
  5. How did they do that ?

Leave a Reply