
What PHP 5.5 might look like - nikic
http://nikic.github.com/2012/07/10/What-PHP-5-5-might-look-like.html
======
Smerity
The introduction of list comprehensions is nice and should replace numerous
functions. For example, I'm not sure why they're adding the array_column
function into PHP 5.5 at the same time as list comprehensions as:

    
    
      $names = array_column($users, 'name');
      // is the same as
      $names = [foreach ($users as $user) yield $user['name']];
    

The only possible reason would be due to a significant speed difference, but
I'd suggest improving the efficiency of the list comprehension system (even if
just for common cases) than adding more functions.

As opposed to the introduction of list comprehensions, I can't say I like the
solution for parameter skipping though... I disagree with the author -- many
optional arguments is not a problem, but only if keyword arguments or a
similar style are used. Consider the example they give:

    
    
      // This create query function in PHP
      create_query("deleted=0", "name", default, default, false);
      // could be represented like this with keyword arguments
      create_query("deleted=0", "name", escape_arguments=false)
    

I tend to find keyword arguments serve the purpose of self documentation as
well -- I still have no clue what the false flag would be for the PHP
create_query statement.

Keyword arguments and many optional arguments can allow for beautiful and
flexible functions, such as the Python Requests library[1].

    
    
      r = requests.get('https://api.github.com/xyz')
      # or we could add a few more complications
      # -- no "defaults" in sight and also self documenting
      r = requests.get('https://api.github.com/xyz',
        auth=('user', 'pass'), timeout=0.5, allow_redirects=True)
    

[1]: <http://docs.python-requests.org/>

~~~
geon
> I'm not sure why they're adding the array_column function

Isn't the function call much more readable than the comprehension?

At least as a beginner, I found the large set of built in functions to be one
of the strongest points of PHP.

~~~
Smerity
One major disadvantage with so many functions is the cluttered global
namespace[1]. PHP only added namespaces in 5.3.0 and can't modularize their
globals into namespaces without causing massive backwards compatibility
problems. PHP is stuck with a polluted global namespace, I'd be wary of adding
more. Mind you, I'm well aware that this feeling could just be as I'm
primarily a Python coder -- in PHP, you perform array_keys($xyz) whilst in
Python it's xyz.keys(). Whilst you might consider Python as cheating by
pushing all the functions onto the objects, it results in a far happier global
namespace[2].

As far as list comprehensions, I tend to find list comprehensions the readable
and self documenting, at least in Python where I most commonly see them. If
nothing else, what is the ordering of the arguments for the equivalent non
list comprehension? With list comprehensions you don't have that impedance.

    
    
      // Python example with filter vs list comprehension
      // Filter requires you to remember the ordering --
      // and does it filter on True or False?
      filter(lambda x: x % 2 == 0, range(10)) --> 0 2 4 6 8
      // The list comprehension is self documenting
      [x for x in range(10) if x % 2 == 0] --> 0 2 4 6 8
    

I can also convert the majority of list comprehensions into English quite
easily -- "output x for each x in range(10) if x is divisible by 2" (though it
may be cleaner if it was "for each x in range(10) [output x] if x is divisible
by 2").

[1]: <http://php.net/quickref.php>

[2]: <http://docs.python.org/library/functions.html> \+
<http://docs.python.org/library/exceptions.html>

~~~
TazeTSchnitzel
>PHP only added namespaces in 5.3.0 and can't modularize their globals into
namespaces without causing massive backwards compatibility problems. PHP is
stuck with a polluted global namespace

They could do what Python did for 3.0, and make a tool similar to Python's
2to3 that replaces global namespace references.

~~~
sirclueless
That sounds like a disaster. I don't think anyone wants to follow Python's
lead on breaking backwards compatibility without a very good reason. A much
better reason than a cluttered namespace.

------
geon
I was confused by the password hashing example since it doesn't appear to use
a salt (which was the main reason to implement it at all). Even more
confusing, the RCF says it will auto generate a salt if none is passed.

The explanation, a bit further down in the eRFC is that the function
password_hash doesn't actually return a password hash, but a string including
the algorithm and options used, the salt and the hash itself.

From the RFC:

> It's important to note that the output of crypt() (and hence
> password_hash()) contains all the information that will be needed to verify
> the hash later. Therefore, if the default hashing algorithm changes, or the
> user changes their algorithm, old hashed passwords would still continue to
> function and will be validated properly.

------
gurkendoktor
> 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.

Given the recent threads about planned obsolescence (Apple) and OS
fragmentation (Android) I'm curious what is missing from XP/2003 that is part
of Vista+. Are there still exciting things happening in the world of OS APIs
that are relevant for server software?

Or does this just mean that noone will actively _test_ the binaries on XP
anymore?

~~~
z92
I can foresee them making a turn on this decision and continuing to support XP
until developers actually stop using XP anymore. XP isn't going away anytime
soon.

It was nice to see short tags "<?" coming back in 5.4. Before that, they used
to say, don't use short tags, it's dangerous, breaks things. But users
resisted it, and every ISP kept it open. And now from PHP 5.4 short tag is ON,
regardless of whether one setts it On or Off in php.ini.

~~~
stephenr
No actually, as of 5.4 <?= is always available. <?= and <? are not the same
thing.

------
bergie
These sound like useful improvements, especially the new getter/setter syntax
and scalar type hinting.

However, what I'd really like to see in next PHP would be the Composer
dependency manager bundled in, a bit like Node.js nowadays ships with NPM.
This has really brought a new world of cross-project code sharing into PHP:

<http://packagist.org/>

I wrote a blog post on why this is important for improving the state of PHP:

[http://bergie.iki.fi/blog/composer_solves_the_php_code-
shari...](http://bergie.iki.fi/blog/composer_solves_the_php_code-
sharing_problem/)

~~~
ircmaxell
I think composer is a bit too young to introduce into the language. Perhaps it
will prove out to be robust, but I'd wait a little while before introducing it
to core...

~~~
wink
When you look at people complaining at the deprecation of 5.1 and 5.2, I'd
rather not have any userland code shipped.

------
musashibaka
17 years old and a PHP Internals tinkerer...

Awesome work Nikita, keep it up!

~~~
ircmaxell
As someone who has worked with him for quite some time, all I can say is so
very much agree. He blows me away left and right with his knowledge, ability
and maturity (especially when it comes to code decisions). He's more senior
than most developers that I know...

So very much agree, keep it up!

------
pbiggar
I was involved with PHP internals when type hinting came up for 5.3, and
helped steer that discussion in some way [1]. It was a truly awful experience
- at the time, the internals community was a very negative and poisonousness
place. Does anyone still involved know if that has been fixed?

[1] oh look, I'm still mentioned in the RFC :) -
<https://wiki.php.net/rfc/scalar_type_hinting_with_cast>

~~~
swivelmaster
Given that you're involved in this - why add "with cast"? I thought the whole
point of the feature, in regards to classes and arrays, is to be absolutely
strict about function arguments. Once you start down the path of "well, as
long as it's sort of like that," then you might as well accept objects that
have toString defined in place of strings. Having worked in a large PHP
project for years and trying to get it to a point of letting new developers
spin up pretty quickly (and use PHPStorm efficiently), STRICT type hinting is
one of the best tools possible!

~~~
pbiggar
So I'm not involved in the current discussion, but I remember some stuff from
the last discussion and in general.

To start, you can consider the problem of type checking of scalars in a
language with implicit type coercions. You're supposed to be able to treat 0
and 0.0 the same. At the same time, if you have a type check that says "int",
you kinda expect to get an int. So "with cast" does that.

I know a lot of people find that ugly, and that you want to strictly that you
must receive an int, but that's just not how people use PHP, and it doesn't
make sense in the context of the language. As an example, you want to be able
to add type checks to all the functions in the standard library, many of whom
treat null, "0", 0 and 0.0 to be the same.

For PHP specifically, there is the additional consideration that PHP is
supposed to be a newbie friendly language. There was a perception in the PHP
internals community that newbie developers could not wrap their head around
the concept of "types". I've heard people say that a developer shouldn't be
required to think about what types his variable might hold. Clearly this is
lunacy for many reasons, but there it is.

~~~
pbiggar
I just read the RFC, and I think it's very good. The only minor quibbles I
have would be using the "compiler" instead of the parser to produce the hint,
and whether or not you should cast if losing precision. But these are minor
issues that should probably be ignored, since this improves the status quo
considerably.

------
giulianob
The "parameter skipping" functionality is really useful but IMO they should
take the same route that C# did with named parameters.

    
    
        function create_query($where, $order_by, $join_type='', $execute = false, $report_errors = true) { ... }
    
        create_query("deleted=0", "name", report_errors: true);
    

can even specify all parameters by name in different order

    
    
        create_query(order_by: "name", report_errors: true, where: "deleted=0");

------
debacle
Pretty exciting, though empty() should be deprecated, not improved upon.

The bit about getting the fully qualified class name is important, but it
still prevents you from doing something like:

    
    
      function builder_factory( $var ) {
        $class = $some_array[ $var ];
    
        return new $class();
      }
    

So you have to write a ton of boilerplate for something that used to be easy
without namespaces, or write namespace traversal into your PHP (which isn't
THAT hard, but is very ugly).

Parameter skipping looks intuitive and useful. Very important as we
incorporate more functional paradigms into the code.

I don't believe scalar type hinting will make it in. There's just too much
discussion around it. IMHO, it should be super strict. "1" is not an integer.

Getters and setters: meh. I guess it's good. Better than what we have now.

I don't believe PHP will do generators or list comprehensions right, so I'm
not holding my breath on those.

~~~
leftnode
Better than parameter skipping would be named parameters so you could just do:

    
    
        function foo($a, $b="10", $c="5", $d="3") { /* .. */ }
    
        foo(5, $c="10");
    

That way $a == 5, $b == "10", $c == "10", and $d == "3". Much better and
cleaner syntax in my opinion and a lot of other languages support something
similar.

~~~
ircmaxell
The problem with that is it's already valid syntax with a different meaning.

    
    
        function foo($a, $b = "10", $c = "20") {}
        foo(1, $c=20);
        var_dump($c); // int(20)
    

The syntax would have to be unambiguous. Perhaps:

    
    
        foo(5, c: 30)
    

or

    
    
        foo(5, $c: 30);
    

or

    
    
        foo(5, $c => 30)
    

or something like that...

~~~
Joeri
What people end up doing in practice is passing in arrays with key/value
pairs. The => syntax would be the closest thing to the current way of doing
things, except you'd get default values and type hinting. I'm all for it!

I'm still looking for a good way to combine array parameters with defaults and
hinting in PHP 5.3. I've had some success using DTO's for primary API's:

    
    
      function foo(SomeDTO $data) { ... }
      foo(new SomeDTO(array("a" => "foo", "b" => 10)));
      
      class SomeDTO extends BaseDTO {
         /** @var string 
             @maxlength 10 */
         public var $a;
         /** @var int */
         public var $b = 20;
      }
    

The BaseDTO class uses reflection to parse the doc comments and figure out how
to validate and set its input. It's the same idea as validation annotations in
java. It works, but it's quite a heavy syntax, and I wish I had a lighter-
weight alternative. I like PHP's loose typing inside an API's class, but when
interfacing between API's I want strict typing.

------
lysol
This is just a "would be nice" sort of post right? The main feature I'd want
(list comprehensions) seems to be just a single programmer's guess at an
upcoming feature with no real evidence.

~~~
courtewing
Pay close attention to the "status" listed under each header. Some of these
features have already landed in master, and others are still in various states
of proposal. The author links to the official RFC for most of the proposed
features.

I'm not sure if the list comprehensions feature has made it past the mailing
list though.

------
Nervetattoo
Consistency in dereferencing is very important. empty() should at some point
be deprecated, but fixing this erratic behavior for now is good imo.

The default value for method arguments is a shockingly bad idea for a new
feature, it only supports the old, bashed upon, code quality that have been
PHPs greatest legacy problem. If anything in this alley I'd like to see named
arguments somehow.

I'm not so sure about property getter/setters as I find the syntax a bit
awkward, all while magic methods lets you create getter/setter based APIs.

~~~
davedx
What's the deal with empty()? I've never used it myself but found people at
the new place I work do use it.

~~~
leftnode
Like the article said, you can't use it with function calls because empty()
itself is a construct of the language and not a function. So,
empty(someFunc()) is an error. You'd have to put the return value of
someFunc() in a variable and test it for emptiness, or do something like if (0
== strlen(someFunc())) { /* .. */ } which is overly verbose and not fast.

------
masklinn
I think a standard password hash API is a good thing (there was a proposal for
such a thing for Python recently on -ideas, though it was essentially rejected
in favor of recommending/using passlib), but I'm wary of having default cost
factors, that seems unwise: what are the defaults, how are they decided to be
ok, and more importantly in what context are they updated over time (and based
on what data)?

~~~
DomBlack
The problem with it in it's current form is it does not allow for an
application pepper.

Also I'd prefer it to support scrypt as well as bcrypt.

~~~
masklinn
> The problem with it in it's current form is it does not allow for an
> application pepper.

Considering:

* no password hash algorithm I know of supports peppers

* that the API allows providing a custom salt

I don't see any issue with the API. If the cryptographic worth of peppers is
ever demonstrated _and_ a password hash is built to use peppers, the pepper
can be provided as an option to that hash algorithm as the salt and cost
already are in the proposed API.

~~~
DomBlack
Every hashing algorithm allows it, even bcrypt. Very simple example;
md5($salt.$pepper.$clearText);

The problem with this API is that if you pass in the "salt" as $salt.$pepper
then the output hash also contains the pepper.

The whole point of a pepper is to keep a second salt out of the database. The
user salt would be in the database, but the pepper should only be in the
application code.

If your database is stolen, but your application code is safe the pepper
increases the complexity of brute forcing, as they need to work out what the
pepper is

~~~
masklinn
> Every hashing algorithm allows it, even bcrypt.

That is not the meaning I intended in my usage of the word "support", but if
you equate "support" and "is compatible with", then this API also "supports"
peppers, just as much as bcrypt does.

> md5($salt.$pepper.$clearText)

How cute, not just md5 but length-extension vulnerable MD5. I'd recommend not
using that scheme for MACs (and more generally not using md5 directly, really,
as there are precious few reasons to do so)

> The problem with this API is that if you pass in the "salt" as $salt.$pepper
> then the output hash also contains the pepper.

Which just happens to be _the exact same way bcrypt's API works_. Here's an
idea: combine the pepper to the password (this is usually done through hmac),
not the salt. That's how you use a pepper and remain compatible with the
Modular Crypt Format.

> The whole point of a pepper is to keep a second salt out of the database
> [blah blah blah]

Contrary to your apparent belief, I am aware of what peppers are, how they are
used and what they're supposed to do.

~~~
comex
A length extension attack is fairly irrelevant for password storage...

------
mikeash
Regarding the "constant dereferencing" proposal, how do you even make a
language parser that can't apply array operations to literals in the first
place? I'm trying very hard not to bash on PHP here, and this is a completely
honest question. I can't figure out how you'd even go about breaking that if
you wanted to. Anyone know the background there?

~~~
pbiggar
This would probably ban "4[5]" but not "$x = 4; $x[5]".

PHP enforces a lot of things in the parser (as opposed to making bytecode and
having a simple type checker). Instead of having a general "expression" type
which can be dereferenced, they have different rules for scalars, strings,
variables, function calls, etc. For a long time, you couldn't dereference the
result of a function call, because the parser didn't allow it, so this is
probably the same.

~~~
mikeash
Enforcing it in the parser seems so horribly wrong. If you want to disallow
stuff like 4[5] at compile time then you should do that in a separate pass on
the AST, not in the parser itself. That's ought to be a semantic error, not a
syntax error. Treating that separately would require all manner of special
cases. But, I guess that must be what they do.

~~~
pbiggar
Yeah, there's tons of special cases in the parser. I worked on phc
(<http://phpcompiler.org>), so I've read the PHP parser and helped write some
of our own. We took the AST approach and it worked out pretty well. But PHP
was written before its authors knew good interpreter design, and its currently
very hard to refactor it out to a better design.

~~~
mikeash
Painful. Thanks for sharing your experience. Cool to ask such a question and
get an answer from someone who's actually built something related.

------
mmuro
Yet another array function. But, array_column does seem super useful.

------
Sander_Marechal
The proposals look great! But I'm missing one thing: Less fatal errors, or a
better way to catch them. Especially for the case of calling a method on a
null value. E.g.

    
    
        $foo->getBar()->getBaz()
    

If getBar() return NULL for some reason, you get a fatal error which you
cannot catch and handle without reverting to uglu hacks with a shutdown
function.

My personal preference would be to have that statement return NULL and raise a
warning or notice, alike to using uninitialized variables.

~~~
smsm42
Don't return null from that function. Return NullObject which has __call() {
return $this; } - then you could chain as many such calls as you want and
they'd be OK with nulls. Then you could check for NullObject as easily as you
could check for null - if($result instanceof NullObject) etc.

------
snorkel
Conspicuously absent from PHP:

    
    
       array_copy()
    

... in order to copy-by-value on arrays containing references. Currently to do
that you have to do a very fragile hack like this:

    
    
       $copy = array_flip(array_flip($original));
    

... which is vulnerable to key-value collisions ... or you have to write your
own homebrew array copy-by-value function.

~~~
TazeTSchnitzel
File a bug report :)

~~~
smsm42
Better yet, file an RFC and a pull request.

~~~
TazeTSchnitzel
Yep. That's what I'm trying to do for something else :D

------
psaintla
If there is scalar type hinting I wonder if that will lead to real method
overloading by adding methods with different signatures or if devs will have
to stick with the __call magic method, which I despise.

------
zapt02
The getters and setters change is looking great! Overall lots of good ideas!

------
velodrome
Is PHP JIT at least on the roadmap?

~~~
RobAley
As far as I am aware, it is under consideration for Zend Engine 3 / PHP6. But
certainly not for 5.5, and probably not in the 5.x series at all. Though how
many 5.x releases are left is anyone’s guess, personally my crystal ball tells
me we will get 5.6 followed by 6. My crystal ball also says we will all have
flying cars by now.

------
ShaneCurran
Laravel already does alot of this stuff ^^^

------
ardillamorris
No matter how much PHP is improved upon, until there is a serious contender
framework for it like Rails or Django, PHP will continue its route to
extinction. Dinosaurs were once big and powerful. They dominated the
landscape. They don't exist anymore.

~~~
mootothemax
_No matter how much PHP is improved upon, until there is a serious contender
framework for it like Rails or Django, PHP will continue its route to
extinction._

I'm not sure if you're serious, but there are plenty of frameworks on a par
with Rails at least (nb: I have zero experience with Django).

At the enterprise level, there's Symfony or Zend:

<http://symfony.com/>

<http://www.zend.com/>

If Rails is your thing, CakePHP shares some concepts (although I'll be the
first to admit CakePHP has many flaws):

<http://cakephp.org/>

Want something lightweight that's easy to jump into? CodeIgniter's the one for
you!

<http://codeigniter.com/>

And finally, my favourite, Kohana. Absolutely infuriating since they
essentially stopped writing documentation for new versions, but if I need to
get something written quickly and reliably, this is my go-to call:

<http://kohanaframework.org/>

There are tonnes of "serious" frameworks for PHP (I've certainly missed out a
few), and frankly, if you're going to try to attack PHP, this is the wrong
angle from which to do so.

~~~
ZoFreX
Please don't recommend CodeIgniter. I'm not normally one for swathing "x is
bad" judgements, but CI is simply not in the same league as the other
frameworks you mentioned.

~~~
zapt02
Tell us why! With the low memory overhead, built-in cache, Active Record (+PDO
support) and easy-to-understand MVC approach, I think it is the best framework
for writing small to medium-sized web applications.

CI is not Zend, but nothing prevents you from using the Zend libraries with a
small CI Library wrapper - I have done so many times in the past, and it works
great.

~~~
ZoFreX
CI gives you very little, and what it gives you is mostly categorically
broken. The total lack of post-redirect-get and insane choices on the session
data front meant I was using a custom session storage library I wrote instead
of the bundled one.

We had issues where the router and loader were not playing nicely at all - we
were using the 404 override option in order to do some custom routing (as the
router was not flexible enough for even a very basic CMS). However because of
how messy the routing code is, and how much of a hack the 404 override was
(last time I checked there were several open bugs regarding this on their
tracker, some over a year old and completely untouched), it completely blitzed
the loaded libraries, so we had to add in more hacks to dodgily clear the
cache of loaded libraries and re-run the loader in order to have them
available. The only other way to do this would have been to modify the core
loader to fix the bug there (but we didn't want to modify core code to make it
easier to keep up to date with framework changes), or completely rewrite the
router (which really needs to be done, it's a mess).

The database abstraction code is very kludgy and basically useless for
anything beyond utterly, utterly basic use cases (there's a reason it's low
overhead - it's low everything, including functionality!)

That's just a few of the things we ran into. By the time we went to production
I estimate that out of the maybe 30% of CodeIgniter we were actually using for
our project, I had re-implemented as custom libraries maybe a third of that
amount just to get some sane behaviour, and work around long-standing bugs.
Overall I got the feeling that the framework had no solid direction, some of
the core components (most critically the loader and router) were quite
obviously piles of hacks rather than having been designed and engineered, and
honestly the framework was not really much more re-usable or robust than our
own custom in-house one. I know it's a very common developer hubris to think
you could write your own framework and do a better job, but in the case of
CodeIgniter I can confidently make that claim.

On the more technical and abstract side, it's insane that it doesn't use
standard PSR loading (so any other library you want to use you have to write a
custom wrapper), and the guidance on making re-usable libraries / modules /
packages (I can't even remember the right terminology, they use these words in
strange ways) is... unclear at best. It uses globals, it's tightly coupled,
everything a decent framework should categorically not be. Overall I would say
that the level of technical ability on people using and contributing to CI is
very low, and most people I've spoken to that think it's great haven't
actually used any other framework (which is, frankly, endemic of a large
portion of the PHP-using world)

Edit: Also if you care about overhead, you're not writing what I would call a
small to medium sized application! _Any_ framework out there worth its salt
(and many that are not) will be able to run your application just fine, it's
extremely unlikely that the PHP layer will be the bottleneck unless you're
writing really terrible code or using a really terrible framework.

