3

If you are a PHP developer you most probably have seen the following notice:

Notice: Only variables should be passed by reference in /somefile.php on line xxx

(Problem extensivley treated in Only variables should be passed by reference)

Example throwing notice:

$string = "hi-dude";
echo end(explode('-', $string));

Working example:

$string = "hi-dude";
$strings = explode('-', $string);
echo end($strings);

Explanation:

Only real variables may be passed by reference, not functions which are returning the correct variable.

However I can not think of a good reason why this notice is happening. It feels unecessary and requires me to write a lot of extra lines of code sometimes. What is the reason for PHP having this strange restriction? Why does this problem even exist?

Blackbam
  • 17,496
  • 26
  • 97
  • 150

2 Answers2

2

end() or array_pop() will return the E_NOTICE with message

Only variables should be passed by reference

The reason is that end() requires a reference, because it makes the current element pointer point to the last element.

You can do it with one line,

$string = "this-is-a-sample-text";
echo substr(strrchr($string, '-'), 1);

DEMO: https://3v4l.org/jO29n

A l w a y s S u n n y
  • 36,497
  • 8
  • 60
  • 103
  • Why do those function even return this notice? – Blackbam Sep 04 '18 at 17:27
  • Thats a big step forward ty. And why does it matter in cases like this where the current element pointer is pointing? If I passed a function which returns an array who cares where the array pointer is? I just want the last value and proceed. – Blackbam Sep 04 '18 at 17:34
  • My English is not very good so it is little bit hard for me to explain you, But I think this is what I want to Say https://stackoverflow.com/a/39277181/1138192 – A l w a y s S u n n y Sep 04 '18 at 17:40
  • Really like this part of the answer: **You cannot create a reference to something (or to something unknown in the memory), that does not exists**. Now I wonder why do they not create this value in memory if it is passed, but that might be another question. – Blackbam Sep 04 '18 at 17:45
  • @Blackbam glad it helps you some how. Best of Luck :) – A l w a y s S u n n y Sep 04 '18 at 17:47
  • Finally I completely understood what was going wrong here and posted an additional answer. Nevertheless thanks for help +1 – Blackbam Sep 05 '18 at 09:47
2

Finally I found a great explanation which helped me to understand this: What's the difference between passing by reference vs. passing by value?

As Daniel Pryden states:

In simplest terms:

  • call by value means that you pass values as function arguments
  • call by reference means that you pass variables as function arguments

In metaphoric terms:

  • Call by value is where I write down something on a piece of paper and hand it to you. Maybe it's a URL, maybe it's a complete copy of War and Peace. No matter what it is, it's on a piece of paper which I've given to you, and so now it is effectively your piece of paper. You are now free to scribble on that piece of paper, or use that piece of paper to find something somewhere else and fiddle with it, whatever.
  • Call by reference is when I give you my notebook which has something written down in it. You may scribble in my notebook (maybe I want you to, maybe I don't), and afterwards I keep my notebook, with whatever scribbles you've put there. Also, if what either you or I wrote there is information about how to find something somewhere else, either you or I can go there and fiddle with that information.

In this case the notice "Only variables should be passed by reference" is still unjustified as we are only interested in retrieving the last value of the array. However the function end() is defined like

mixed end ( array &$array )

The & sign which states passing by reference is there for a certain reason: end() is not just returning the last element of an array, it also changes its internal pointer to the end. Therefore the array is modified.

If we only would return the last element of an array without touching the array there would be no need to pass the array by reference and we would not get this notice. But end() is somehow the wrong function for that.

What if there is no justification for me getting this notice? Note that also the function to be called might be defined wrong. In my case I hade a function defined like this:

/**
 * Flatten an array by one level if only needing a certain key value from a sub array.
 *
 * Example: [["foo"=>"bar","foo"=>"cheese"]]
 * Result: ["bar","cheese"]
 *
 * @param $array: The input array.
 * @param $key: The key to flatupshift. Default is 0.
 * @return $array: The result
 */
private function array_flatupshift(&$array, $key = 0) {
    $a = [];
    foreach ($array as $item) {
        if (is_object($item)) {
            array_push($a, $item->$key);
        } else if (is_array($item)) {
            array_push($a, $item[$key]);
        }
    }
    return $a;
}

This is simply a wrong function definition. So if you also get notices like this: Check if the function you call is defined correctly. Passing by reference does not make sense here as the array being passed is not touched in any way. Therefore the function definition should be without the "reference &/":

private function array_flatupshift($array, $key = 0) {

There are some cases where you MIGHT use the error control operator if you know what you are doing. Therefore:

$string = "hi-dude";
echo @end(explode('-', $string));

... would be o.k. I guess is the result of explode is not needed anymore. However notice the drawbacks of suppressing all possible errors. Please correct me if I go wrong here.

Blackbam
  • 17,496
  • 26
  • 97
  • 150
  • Yep, that's the crucial point: whether the function *actually* modifies the variable passed to it, by using the `&` notation, it's saying that it *wants to* modify the variable, so if you pass a non-variable, you're "disobeying" that request. – IMSoP Sep 05 '18 at 10:29
  • 1
    It's also worth noting that the `@` operator has unfortunate performance effects sometimes (because PHP has to stop to switch error handling off and back on again, it can't optimise the code around that line in ways which would otherwise be OK). – IMSoP Sep 05 '18 at 10:30