What PHP 5.5 might look like
PHP 5.4 was released just four months ago, so it probably is a bit too early to look at the next PHP version. Still I’d like to give all the people who aren’t following the internals mailing list a small sneak peek at what PHP 5.5 might look like.
But be sure to understand this: PHP 5.5 is in an early development stage, so nobody knows how the end result will look like. All I am talking about here are proposals. I’m pretty sure that not all of the things listed below will go into PHP 5.5, or at least not in their current form.
So, don’t get too excited about this :)
The list of new features / proposals is rather large and not sorted by significance. So if you don’t want to read through all of it, here are the four features I personally am most excited about:
Now, without further ado, the list of stuff being worked on for PHP 5.5:
Backwards compatibility breaks
We’ll start off with two changes that already landed in master and represent BC breaks (to some degree at least):
Windows XP and 2003 support dropped
Status: landed; Responsible: Pierre Joye
PHP 5.5 will no longer support Windows XP and 2003. Those systems are around a decade old, so PHP is pulling the plug on them.
/e modifier deprecated
Status: landed; Responsible: myself
The e
modifier instructs the preg_replace
function to evaluate the replacement string as PHP code
instead of just doing a simple string replacement. Unsurprisingly this behavior is a constant source of problems and
security issues. That’s why use of this modifier will throw a deprecation warning as of PHP 5.5. As a replacement you
should use the preg_replace_callback
function. You can find more information on this change
in the corresponding RFC.
Function and class additions
Next we’ll look at some the planned function and class additions:
boolval()
Status: landed; Responsible: Jille Timmermans
PHP already implements the strval
, intval
and floatval
functions. To be consistent the boolval
function is now
added, too. It does exactly the same thing as a (bool)
cast, but can be used as a callback function.
hash_pbkdf2()
Status: landed; Responsible: Anthony Ferrara
PBKDF2 stands for “Password-Based Key Derivation Function 2” and is - as the name already says - an algorithm for deriving a cryptographic key from a password. This is required for encryption algorithms, but can also be used for password hashing. For a more extensive description and usage examples see the RFC.
Intl additions
Status: landed; Responsible: Gustavo André dos Santos Lopes
There have been many improvements to the intl extension. E.g. there will be new IntlCalendar
,
IntlGregorianCalendar
, IntlTimeZone
, IntlBreakIterator
, IntlRuleBasedBreakIterator
,
IntlCodePointBreakIterator
classes. I sadly don’t know much about the intl extension, so I will just direct you to
the mailing list announcements for Calendar and BreakIterator, if you want to
know more.
array_column()
Status: proposed; Responsible: Ben Ramsey
There is a proposal pending for a new array_column
(or array_pluck
) function that would behave as
follows:
$userNames = array_column($users, 'name');
// is the same as
$userNames = [];
foreach ($users as $user) {
$userNames[] = $user['name'];
}
So it would be like fetching a column from a database, but for arrays.
A simple API for password hashing
Status: proposed; Responsible: Anthony Ferrara
The recent password leaks (from LinkedIn etc) have shown that even large websites don’t get how to properly hash
passwords. People have been advocating the use of bcrypt for years, but still most people seem to be using completely
unsafe sha1
hashes.
We figured that the reason for this might be the really hard to use API of the crypt
function. Thus we would
like to introduce a new, simple API for secure password hashing:
$password = "foo";
// creating the hash
$hash = password_hash($password, PASSWORD_BCRYPT);
// verifying a password
if (password_verify($password, $hash)) {
// password correct!
} else {
// password wrong!
}
The new hashing API comes with a few more features, which are outlined in the RFC.
Language changes
Now comes the really interesting stuff: New language features and enhancements.
Constant dereferencing
Status: landed; Responsible: Xinchen Hui
“Constant dereferencing” means that array operations can be directly applied to string and array literals. Here two examples:
function randomHexString($length) {
$str = '';
for ($i = 0; $i < $length; ++$i) {
$str .= "0123456789abcdef"[mt_rand(0, 15)]; // direct dereference of string
}
}
function randomBool() {
return [false, true][mt_rand(0, 1)]; // direct dereference of array
}
I don’t think that this feature is of much use in practice, but it makes the language a bit more consistent. See also the RFC.
empty() works with function calls (and other expressions)
Status: landed; Responsible: myself
Currently the empty()
language construct can only be used on variables, not on other expressions. In particular code
like empty($this->getFriends())
would throw an error. As of PHP 5.5 this becomes valid code. For more info see the
RFC.
Getting the fully qualified class name
Status: proposed; Responsible: Ralph Schindler
PHP 5.3 introduced namespaces with the ability to alias classes and namespaces to shorter versions. This does not apply to string class names though:
use Some\Deeply\Nested\Namespace\FooBar;
// does not work, because this will try to use the global `FooBar` class
$reflection = new ReflectionClass('FooBar');
To solve this a new FooBar::class
syntax is proposed, which returns the fully qualified name of the class:
use Some\Deeply\Nested\Namespace\FooBar;
// this works because FooBar::class is resolved to "Some\\Deeply\\Nested\\Namespace\\FooBar"
$reflection = new ReflectionClass(FooBar::class);
For more examples see the RFC.
Parameter skipping
Status: proposed; Responsible: Stas Malyshev
If you have a function accepting multiple optional parameters there is currently no way to change just the last one, leaving all others at their default.
Taking the example from the RFC, if you have a function like the following:
function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) { ... }
Then there is no way to set $report_errors = false
without replicating the other two default values. To solve this
a way of skipping parameters is proposed:
create_query("deleted=0", "name", default, default, false);
Personally I’m not particular fond of this proposal. In my eyes code that needs this feature is just badly designed. Functions shouldn’t have 12 optional parameters.
Scalar typehinting
Status: proposed; Responsible: Anthony Ferrara
Scalar typehinting was originally planned to go into 5.4, but never made it due to lack of consensus. For more info on why scalar typehints haven’t made it into PHP yet, see: Scalar typehints are harder than you think.
For PHP 5.5 the discussion has come up again and I think there is a fairly decent proposal for scalar typehints with casting.
It would work by casting the input value to the specified type, but only if the cast can occur without data loss. E.g.
123
, 123.0
, "123"
would all be valid inputs for an int
parameter, but "hallo world"
would not. This matches
the behavior of internal functions.
function foo(int $i) { ... }
foo(1); // $i = 1
foo(1.0); // $i = 1
foo("1"); // $i = 1
foo("1abc"); // not yet clear, maybe $i = 1 with notice
foo(1.5); // not yet clear, maybe $i = 1 with notice
foo([]); // error
foo("abc"); // error
Getters and setters
Status: proposed; Responsible: Clint Priest
If you’ve never been a fan of writing all those getXYZ()
and setXYZ($value)
methods, then this should be a welcome
change for you. The proposal adds a new syntax for defining what should happen when a property is set / read:
class TimePeriod {
public $seconds;
public $hours {
get { return $this->seconds / 3600; }
set { $this->seconds = $value * 3600; }
}
}
$timePeriod = new TimePeriod;
$timePeriod->hours = 10;
var_dump($timePeriod->seconds); // int(36000)
var_dump($timePeriod->hours); // int(10)
There are also some more features like read-only properties. If you want to know more, have a look at the RFC.
Generators
Status: proposed; Responsible: myself
Currently custom iterators are used only rarely, because their implementation requires lots of boilerplate code. Generators solve this issue by providing an easy and boilerplate-free way to create iterators.
For example, this is how you could define the range
function, but as an iterator:
function *xrange($start, $end, $step = 1) {
for ($i = $start; $i < $end; $i += $step) {
yield $i;
}
}
foreach (xrange(10, 20) as $i) {
// ...
}
The above xrange
function has the same behavior as the builtin range
function with one difference: Instead of
returning an array with all the values, it returns an iterator which generates the values on-the-fly.
For more in-depth introduction into the topic see the RFC.
List comprehensions and generator expressions
Status: proposed; Responsible: myself
List comprehensions provide a simple way to do small operations on arrays:
$firstNames = [foreach ($users as $user) yield $user->firstName];
The above list comprehension is equivalent to the following code:
$firstNames = [];
foreach ($users as $user) {
$firstNames[] = $user->firstName;
}
It is also possible to filter arrays this way:
$underageUsers = [foreach ($users as $user) if ($user->age < 18) yield $user];
Generator expressions are similar, but return an iterator (which generates the values on-the-fly) instead of an array.
For more examples see the mailing list announcement.
Wrapping up
As you can see, there is a lot of awesome stuff being worked on for PHP 5.5. But as I already said, PHP 5.5 is still very young, so we don’t know for sure what will get in and what will not.
If you want to stay updated on the new features or want to help out in discussions and/or development, be sure to subscribe to the internals mailing list.
Comments welcome!