Only variables can be passed by reference
Solution 1
array_pop() tries to change that value which is passed as parameter. Now in your second example this is the return value from array_slice(). In engine terms this is a "temporary value" and such a value can't be passed by references. what you need is a temporary variable:
function foo(){
$a=explode( '/' , 'a/b/c');
$b=array_slice($a,-2,1);
$c=array_pop($b);
return $c;
}
print_r(foo());
Then a reference to $b can be passed to array_pop(). See http://php.net/references for more details on references.
Solution 2
Here is what I get when trying your second php code snippet in php-cli after setting error_reporting to E_ALL | E_STRICT
gparis@techosaure:~/workspace/universcine.com$ php -a
Interactive shell
php > function foo(){
php { $a=explode( '/' , 'a/b/c');
php { $c=array_pop(array_slice($a,-2,1));
php { return $c;
php { }
php > print_r(foo());
PHP Strict standards: Only variables should be passed by reference in php shell code on line 3
PHP Stack trace:
PHP 1. {main}() php shell code:0
PHP 2. foo() php shell code:1
As you can see, it's only strict standards here. And you can easily let your custom error handler ignore them (based on the value you get : 2048 for instance, here).
As of php 5.3, E_ALL does not include E_STRICT, look at this :
php > foreach(array("E_ALL", "E_DEPRECATED", "E_STRICT", "E_NOTICE", "E_PARSE", "E_WARNING") as $const) echo $const . " :\t" . constant($const) ."\t". decbin(constant($const)). "\n";
E_ALL : 30719 111011111111111
E_DEPRECATED : 8192 10000000000000
E_STRICT : 2048 100000000000
E_NOTICE : 8 1000
E_PARSE : 4 100
E_WARNING : 2 10
As of php 5.4, E_ALL
does include E_STRICT
:
E_ALL : 32767 111111111111111
E_DEPRECATED : 8192 10000000000000
E_STRICT : 2048 100000000000
E_NOTICE : 8 1000
E_PARSE : 4 100
E_WARNING : 2 10
Solution 3
It's a memory corruption issue (according to PHP dev team). Just throw in an assignment:
function foo(){
$b = array_pop($arr = array("a","b","c"));
return $b;
}
print_r(foo());
:
function foo(){
$a = explode( '/' , 'a/b/c');
$c = array_pop($arr = array_slice($a,-2,1));
return $c;
}
print_r(foo());
The second produces an E_STRICT. You can handle that differently in your error handler if you wish (if you don't want to change those functions).
Solution 4
array_pop()
changes that value passed to it which is where the error is coming from. A function cannot be changed. In other words, you need to assign the array to a variable first (ref: manual), and then run array_pop()
.
The code you need is this:
function foo(){
$a = array("a","b","c");
$b = array_pop($a);
return $b;
}
Edit: Both functions you mentioned have the same problem. Assign the array to a variable and pass the variable to array_pop()
.
Solution 5
I think that now (since php 5) it should be:
function &foo(){ //NOTICE THE &
$b=array_pop(array("a","b","c"));
return $b;
}
print_r(foo());
and
function &foo(){ //NOTICE THE &
$a=explode( '/' , 'a/b/c');
$c=array_pop(array_slice($a, $b = -2, $c = 1)); //NOW NO DIRECT VALUES ARE PASSED IT MUST BE VARIABLES
return $c;
}
print_r(foo());
but i'm just a begginer :)
Related videos on Youtube
zaf
Updated on October 24, 2020Comments
-
zaf over 3 years
I had the bright idea of using a custom error handler which led me down a rabbit hole.
Following code gives (with and without custom error handler): Fatal error: Only variables can be passed by reference
function foo(){ $b=array_pop(array("a","b","c")); return $b; } print_r(foo());
Following code gives (only with a custom error handler): (2048) Only variables should be passed by reference
function foo(){ $a=explode( '/' , 'a/b/c'); $c=array_pop(array_slice($a,-2,1)); return $c; } print_r(foo());
The second one worries me since I have a lot of 'compact' code. So, I either ditch the bright idea of using a custom error handler (to improve my logging module) or expand all my code.
Anyone with better ideas? Also, WTF?
UPDATE:
Thanks to the answers I've learnt something about how php does error handling. The confusion of E_ALL not including E_STRICT (php 5) is not cool.
On top of all this, creating your own custom error handler enables E_STRICT by default and thats where problems start.
The moral of the story is to use your own error handler to catch them ALL and use the error constants (E_STRICT, E_USER_WARNING, E_USER_ERROR, etc.) to do your filtering.
As for the 'memory corruption issue' with variable references and certain functions, what can I say? Doubly uncool. I'll (which doesn't mean you should) ignore E_STRICT in my error handler and life goes on.
-
MSpreij over 12 years$b=current(array_reverse(array("a","b","c"))); // yes, it's silly, but it works :)
-
-
zaf almost 14 yearsI saw that trick somewhere. Does this apply to all or some functions?
-
webbiedave almost 14 yearsYou can throw assignment in any function. But not in language constructs, such as
empty
. -
greg0ire almost 14 yearsNo it does not, I edited my post to add an explainatory code snippet. See the missing 1 in E_ALL? If you add E_STRICT, you get 111111111111111! Means jackpot!
-
zaf almost 14 yearsThis seriously hinders my kung-fu-ness.
-
johannes almost 14 yearsThe assignment in the parameter list is undefined behavior. with array_pop($arr = array("a","b","c")); it is not clear what will happen first - $arr = array("a","b","c") or array_pop($arr) or array_pop(array("a","b","c")); and can change between all releases.
-
johannes almost 14 yearsin PHP 5.3 E_ALL contains E_STRICT
-
webbiedave almost 14 years@johannes: Why do you say that?
-
greg0ire almost 14 yearsNo, but it will in php 6. See this post : stackoverflow.com/questions/1638238/…
-
voetsjoeba over 12 years@johannes: No, not really. The value of an assignment expression is the value assigned.. Hence, array_pop operates on the returned value of the assignment, which is necessarily evaluated first before the function can be applied.
-
zaf over 12 yearsThanks for the answer. I don't have time to try it but are you saying that adding a '&' makes it work? And what does it do? I'll check it tomorrow.
-
MrWhite over 10 yearsActually, E_STRICT is included in E_ALL from PHP 5.4 (as is now stated in that linked question) - see the PHP Manual: php.net/manual/en/errorfunc.constants.php - However, w3schools.com still incorrectly reports that it is only included from PHP 6.
-
greg0ire over 10 years@w3d : you're right, I updated my answer, feel free to do so yourself if you see mistakes.
-
Jason over 7 yearsIt may be a little easier on the brain if the binary numbers had their units column aligned, i.e. right aligned.
-
greg0ire over 7 yearsnice catch @Jason , fixed it