Search code examples
phpparsingsyntaxassignment-operator

PHP5 - Assignment operation result not treated as object by parser


I'm a bit confused about a parsing error :

class Foo{
    public function some_function(){}        
}

($foo = new Foo())->some_function();

yields

PHP Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR), expecting ',' or ';'

Here is what php-langspec states about a simple assignment expression:

The type and value of the result is the type and value of the left-hand operand after the store (if any [see below]) has taken place. The result is not an lvalue.

Now as I understand it, the assignment result should be equivalent to the variable except it would not be an lvalue (no assignment possible). So why is there an error?

Am I missing something?

EDIT

php version is 5.5.9

This is not related to chaining methods, this is a parsing error not a runtime error.


Solution

  • Short answer: These kind of expressions work fine now in PHP 7.x. Yeey!


    Long answer: PHP's "hand crafted parser" has severe limitations, especially in PHP < 7.0. Lots of complex expressions that you would expect to work, don't.

    But it least it keeps its own weird "symmetry": just as it doesn't work for applying the -> operator to the result of an assignment, it also doesn't work for applying the array indexing operator [...].

    For example (trying this on PHP 5.6.23):

    >>> ($x = new stdClass())->foo                                
    PHP Parse error: Syntax error, unexpected T_OBJECT_OPERATOR on line 1
    
    >>> $x = new stdClass()                                 
    => {#334}           
    >>> $x->foo                                             
    PHP error:  Undefined property: stdClass::$foo on line 1
    >>> // this above is the "correct" error you would expect here
    
    
    >>> ($x = ['name' => 'J'])['name']                     
    PHP Parse error: Syntax error, unexpected '[' on line 1
    
    >>> $x = ['name' => 'J']                
    >>> $x['name']           
    => "J"                  
    

    Pure speculation: I imagine that fixing these parser inconsistencies was simple, but PHP's core developers' reasoning for not doing this could sound something like "but fixing this would encourage a really bad coding style, since everyone agrees using the results of assignments is a bad practice, so since there is already so much bad PHP code in the wild, why add a fix that would encourage people to write even more bad code". Thankfully, reason prevailed with PHP 7.0.

    History: I some past PHP versions, can't remember exactly which, even code like my_function()['attr1'] or $foo->myMethod()->myField was unparse-able, but it had legitimate uses in good code, so the parser got fixed for this to work.