Home » Php » php – Is there a switch to disable "cannot use temporary expression in write context" error?

php – Is there a switch to disable "cannot use temporary expression in write context" error?

Posted by: admin July 12, 2020 Leave a comment

Questions:

The error was added in PHP7 and I have problem with such code as:

(some complex expression)->my_property = 1

Please note I am assigning to the field of the object, not to the object itself (assigning to temporary object does not make sense, I agree, but here it is not the case).

This gives me an error “cannot use temporary expression in write context”. When I rewrite this as:

$tmp = (some complex expression);
$tmp->my_property = 1;

Everything is fine. The problem is I have to have single expression (assignment is an expression), and since PHP does not support comma operator now I am toasted with two statements.

For me this is huge difference, because I cannot pass entire code as an expression further. Everything is valid inside that “complex expression” so I would love to simply disable that check in PHP.

Is it possible? How?

My code is written automatically (it is generated) and the outcome of the expression is a valid PHP object, the problem is PHP somehow does not notice it. Besides, the second form works.

Update: this is an example of complex expression I mentioned above:

(($a = foo()) === 0 ? $a : bar())
How to&Answers:

I’m going to say no.

Everything is valid inside that “complex expression” so I would love to simply disable that check in PHP.

I think the issue here is that disallowing writing to temporary expressions is not simply a “check” in PHP but a part of the language as of 7.1 (introduced in 5c2120b).

As of 5c2120b, the language grammar has been updated to redefine what is deferenceable as:

dereferencable:
        variable                { $$ = $1; }
    |   '(' expr ')'            { $$ = $2; zend_do_begin_variable_parse(TSRMLS_C); $$.EA = 0; }
    |   dereferencable_scalar   { $$ = $1; zend_do_begin_variable_parse(TSRMLS_C); $$.EA = 0; }
;

Source on GitHub

Additionally, you’ll notice that the sources of those errors in the codebase don’t check anything before producing an error, e.g. 1 and 2.

The workaround would be to downgrade to a version of PHP that allowed this.

Answer:

I had this error come up while refactoring some badly written code:

class MyClass {

    static $cache = [];

    public function myFunction() {
            $this->cache['foo'] = 'bar';
    }

I rewrote this to fix the non-static reference to $cache inside myFunction:

class MyClass {

    static $cache = [];

    public function myFunction() {
            self::cache['foo'] = 'bar';
    }

Notice I missed the $ and should have written self::$cache['foo'].

This produced the error cannot use temporary expression in write context, which wasn’t particularly helpful. In my case there was nothing wrong with what I was trying to do, just simple typo.

Answer:

This is very simple to understand.
When you try to call Someclass::somevar, it means, that you’r trying to call “const” var from class, i.e constant variable, like “define()”, but inside class. But when yor’r calling Someclass::$somevar, you’r calling “static” var, similar to object $someclass->somevar.
This is just a very simple explanation for beginners or php-dummies.
For more understanding there is some examples http://php.net/manual/en/language.oop5.static.php

Answer:

This is an assignment error. You are running a statement like “(($a = foo()) === 0 ? $a : bar())” but the result isn’t a class instance or variable. It’s just a random piece of code that ran. That’s why your second answer works because you are assigning the statement to the class $tmp. Likewise when Henry used “self::cache[‘foo’] = ‘bar’;” that also was an assignment to a statement, not a member variable. When he made it a variable the code worked.

If you want this on one line you would either have to keep with the original class $a and do $a->my_property = 1 or go with your second option and assign the code to a class object you create ($tmp = (($a = foo()) === 0 ? $a : bar())->my_property = 1). This code also assumes $a has a public member “my_property”.