PHP 5.5 was
recently released, introducing several exciting new features to the
language. In this article, we’ll go through some of the most interesting
additions and discuss the benefits they provide to developers.
Generators
Generators
are one of the most eagerly anticipated new features. They provide a
way to handle iteration without having to write a class that implements
the
Iterator
interface.
Making a class conform to the Iterator interface requires a substantial
amount of boilerplate code, so being able to avoid this by using
generators can significantly reduce the size and complexity of code that
developers must write.
Generators derive their functionality from the new
yield
keyword. A generator looks very similar to a normal function, but
instead of returning a single value, a generator may yield any number of
values.
To properly illustrate the power of generators, an example is needed. Consider PHP’s
range()
function, which returns an array of the values between the $start
and $end
arguments. We can use range()
as follows:<?php foreach (range(0, 1000000) as $number ) { echo $number ; } |
The problem in this example is that the array returned by
range()
will occupy a lot of memory (over 100mb according to the PHP manual).
While the above code is a trivial demonstration, there are plenty of
real-world situations where large arrays of data are constructed, often
taking a long time to build and occupying a lot of memory.
With the introduction of generators, it’s now easy to tackle this problem without the inconvenience of having to write an
Iterator
class. Generators do not construct a large array, but rather return a
single element at a time as they are iterated. Consider this
modification to the above code, now using a generator to produce the
range of values:<?php // define a simple range generator function generateRange( $start , $end , $step = 1) { for ( $i = $start ; $i < $end ; $i += $step ) { // yield one result at a time yield $i ; } } foreach (generateRange(0, 1000000) as $number ) { echo $number ; } |
This code produces exactly the same result as the
first example, but without producing a large array to store all the
values. According to the manual, this reduces the memory footprint to
less than a single kilobyte – a huge saving compared with the original
example.
Password Hashing
The new password hashing API
is one of the most important and useful features added in PHP 5.5. In
the past, developers have had to rely on the somewhat confusing
crypt()
function, which is poorly documented in the PHP manual. The
introduction of a simplified set of functions to handle password hashing
will make it much easier for developers to understand and implement
secure password hashing for their sites.
The new API introduces two new functions,
password_hash()
and password_verify()
. Calling password_hash($password, PASSWORD_DEFAULT)
will return a strong hash using bcrypt, with salting handled automatically. Verifying the password later is as easy as checking the result of password_verify($password, $hash)
.
The API uses bcrypt by default, but in the future
new algorithms may be introduced to provide even more secure methods of
hashing. Developers can specify their own bcrypt work factor to adjust
the strength of the hashes produced, and can also use their own salts
instead of the automatic salt generation (although the manual
discourages this).
Finally
PHP 5.5 adds support for the
finally
keyword, a much-requested feature found in many other languages with exception handling. finally
allows developers to specify code to be run at the end of try
and catch
blocks, regardless of whether an exception was thrown or not, before the normal execution flow resumes.
Without the
finally
keyword, developers were sometimes be forced to repeat code within both the try
and catch
blocks to handle cleanup tasks. For example, in the following example the call to releaseResource()
must be made in two places:<?php function doSomething() { $resource = createResource(); try { $result = useResource( $resource ); } catch (Exception $e ) { releaseResource( $resource ); log( $e ->getMessage()); throw $e ; } releaseResource( $resource ); return $result ; } |
With the addition of
finally
, we can eliminate the duplicate code:?php function doSomething() { $resource = createResource(); try { $result = useResource( $resource ); return $result ; } catch (Exception $e ) { log( $e ->getMessage()); throw $e ; } finally { releaseResource( $resource ); } } |
In the modified version, we call the cleanup function
releaseResource()
in the finally
block where we know it will always be called. Note that even though the try
block returns a value, the finally
block will still be called before the return
statement is executed and normal execution continues.Array and String Literal Dereferencing
Array and string literals can now be dereferenced using array access syntax:
<?php // array dereferencing - returns 3 echo [1, 3, 5, 7][1]; // string dereferencing - returns "l" echo "hello" [3]; |
This feature was added primarily to improve the
consistency of the language, and probably won’t revolutionize the way we
write PHP. However, there are some interesting applications to
consider, such as the following:
<?php $randomChar = "abcdefg0123456789" [mt_rand(0, 16)]; |
Using empty() with Function Calls and Expressions
The
empty()
construct can now be used with function calls and other expressions. For example, empty($object->getProperty())
is valid code in PHP 5.5. This makes it possible to use empty()
on the return value of functions without capturing the value in a variable first. Class Name Resolution
Since the introduction of namespaces
in PHP 5.3, it has become common practice to use extensive namespacing
to organize classes in PHP projects. However, until now it has been
difficult to retrieve a fully-qualified class name as a string. Consider
the following code:
<?php use NamespacedClassFoo; $reflection = new ReflectionClass( "Foo" ); |
This will fail as PHP will attempt to use the global
Foo class instead of the namespaced class. In PHP 5.5, it is now
possible to retrieve the full namespaced class name as a string using
the
class
keyword:<?php use NamespacedClassFoo; $reflection = new ReflectionClass(Foo:: class ); |
This will now work as intended, as
Foo:class
will resolve to Namespaced\Class\Foo
.Changes to foreach
The
list()
construct in PHP allows the values of an array to be easily assigned to variables. For example:<?php $values = [ "sea" , "blue" ]; list( $object , $description ) = $values ; // returns "The sea is blue" echo "The $object is $description" ; |
It’s now possible to use
list()
with multidimensional arrays within foreach
loops. For example:<?php $data = [ [ "sea" , "blue" ], [ "grass" , "green" ] ]; foreach ( $data as list( $object , $description )) { echo "The $object is $descriptionn" ; } /* Outputs: The sea is blue The grass is green */ |
This is a powerful new feature that has the potential to make iterating through nested arrays much easier and cleaner.
foreach
loops can now also handle
non-scalar values as iterator keys, which means that element keys may
have values that are not strings or integers. Conclusion
PHP 5.5 offers many improvements to facilitate PHP
development. In addition to new features, a long list of bugs have been
resolved in this release (see the changelog for details), and various
optimizations and enhancements have been made to improve performance and
stability.
Will you be upgrading to PHP 5.5? Let us know in the comments.
No comments:
Post a Comment