It was noted in another question that wrapping the result of a PHP function call in parentheses can somehow convert the result into a fully-fledged expression, such that the following works:
<?php
error_reporting(E_ALL | E_STRICT);
function get_array() {
return array();
}
function foo() {
// return reset(get_array());
// ^ error: "Only variables should be passed by reference"
return reset((get_array()));
// ^ OK
}
foo();
I'm trying to find anything in the documentation to explicitly and unambiguously explain what is happening here. Unlike in C++, I don't know enough about the PHP grammar and its treatment of statements/expressions to derive it myself.
Is there anything hidden in the documentation regarding this behaviour? If not, can somebody else explain it without resorting to supposition?
Update
I first found this EBNF purporting to represent the PHP grammar, and tried to decode my scripts myself, but eventually gave up.
Then, using phc
to generate a .dot
file of the two foo()
variants, I produced AST images for both scripts using the following commands:
$ yum install phc graphviz
$ phc --dump-ast-dot test1.php > test1.dot
$ dot -Tpng test1.dot > test1.png
$ phc --dump-ast-dot test2.php > test2.dot
$ dot -Tpng test2.dot > test2.png
In both cases the result was exactly the same:
Array()
with uppercase A? afaik, the language construct is writtenarray()
– MicrodontArray
. – Pluralismreset
. A variable obviously will always work by reference, which leaves us with the functioncall which is only checked at execution because of the possibility to have something like$variablewithafunctionname()
. Why the()
would makereset
not complain... That would mean at the timereset
gets its input it is a reference (refcount > 1), which would mean the expression(get_array())
leaves some zval in memory... – Beauvoirreturn reset((get_array()?:0));
) is already at compile time and the wording is much more harsh: "Fatal error: Only variables can be passed by reference" (and wrong, if a function returns a reference it's all fine). Many flags are checked prior giving the strict notice, I smell somewhere therein it lies but I do not know much about PHP internals: php-trunk/Zend/zend_vm_execute.h line 10853~ – Oddityreset((get_array()?:0));
is an error at compile time because of the0
. try something likereset((get_array()?:$var));
: that can have proper outcomes, but still yields a fatal. – Beauvoirdebug_zval_dump(get_array());
gives one refcount btw., using parenthesis makes no difference but this can be misleading. – Odditydebug_zval_dump(get_array());
anddebug_zval_dump((get_array()));
gives the same result, except the first one generates a STRICT notice. – Didacticget_array
to a reference does not yield any usable results either. I don't think we can get any usable info in PHP, so some brave soul will have to delve through the spaghetti that is the PHP C-source to get a definitive answer. – Beauvoir