only variables should be passed by reference php
PHP: Why should only variables be passed by reference?
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
Example throwing notice:
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?
2 Answers 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,
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 metaphoric terms:
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
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:
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 &/»:
There are some cases where you MIGHT use the error control operator if you know what you are doing. Therefore:
Only variables should be passed by reference
Any ideas? After 2 days still stuck.
12 Answers 12
Assign the result of explode to a variable and pass that variable to end :
The problem is, that end requires a reference, because it modifies the internal representation of the array (i.e. it makes the current element pointer point to the last element).
Php 7 compatible proper usage:
save the array from explode() to a variable, and then call end() on this variable:
btw: I use this code to get the file extension:
The reason is that the argument for end is passed by reference, since end modifies the array by advancing its internal pointer to the final element. If you’re not passing a variable in, there’s nothing for a reference to point to.
See end in the PHP manual for more info.
PHP complains because end() expects a reference to something that it wants to change (which can be a variable only). You however pass the result of explode() directly to end() without saving it to a variable first. At the moment when explode() returns your value, it exists only in memory and no variable points to it. You cannot create a reference to something (or to something unknown in the memory), that does not exists.
Or in other words: PHP does not know, if the value you give him is the direct value or just a pointer to the value (a pointer is also a variable (integer), which stores the offset of the memory, where the actual value resides). So PHP expects here a pointer (reference) always.
But since this is still just a notice (not even deprecated) in PHP 7, you can savely ignore notices and use the ignore-operator instead of completely deactivating error reporting for notices:
Since it raise a flag for over 10 years, but works just fine and return the expected value, a little stfu operator is the goodiest bad practice you are all looking for:
Just as you can’t index the array immediately, you can’t call end on it either. Assign it to a variable first, then call end.
PHP offical Manual : end()
The array. This array is passed by reference because it is modified by the function. This means you must pass it a real variable and not a function returning an array because only actual variables may be passed by reference.
The answer given elsewhere,
is correct and valid. It accomplishes what you are trying to do.
The end() function does not do quite what you think it does. This is related to how the PHP array data structure works. You don’t normally see it, but arrays in PHP contain a pointer to a current element, which is used for iteration (like with foreach ).
The output of explode() is not an actual array. It is a function output. Therefore, you cannot run end(explode()) because you violate language requirements.
Simply setting the output of explode() in a variable creates the array that you’re looking for. That created array has a current element pointer. Now, all is once again right in the world.
So what about the parentheses?
This is not a bug. Once again, it’s a language requirement.
The extra parentheses (like end((explode())) ) do more than just grouping. They create an inline instance variable, just like setting the function output to a variable. You may think of it as a lambda function that is executed immediately.
This is another correct and valid solution. It is perhaps a better solution, as it takes less space. A good reviewer or maintainer should grok what you’re trying to do when they see the extra parentheses.
If you use a linter or SCA program like PHPCS, that may dislike the extra parentheses, depending on the linting profile you’re using. It’s your linter, tell it what you want it to do for you.
I’ll just use the @ prefix
This solution is valid, however incorrect. It is valid because it solves the problem. That’s about the end of its merit.
Suppressing errors is always bad practice. There are many reasons why. One very large one is that you are trying to suppress one specific error condition (one that you have created), but the error suppression prefix suppresses all errors.
In this case, you will probably get away with this. However, engaging in bad programming habits is cheating and will likely lead you to cheat more and bigger in the future. You will be responsible for bad code. But I’m not the Code Police and it’s your code. It’s valid because it solves the problem.
Okay, so what’s the best answer?
This has the added benefit that it actually does what you want, which is finding the extension on a file name. There is a subtle difference.
Once again, I’m not the Code Police. Do what suits you best.
Как пофиксить «Only variables should be passed by reference»?
Как исправить положение? Заранее благодарен!) (До переноса сайта с виртуального хостинга PHP5.6 на VestaCP всё работало, вот незадача.
Notice: Only variables should be passed by reference in /home/admin/web/shopspeed.ru/public_html/engine/include/constants.php on line 10
Проблема в строчке 10, но вы привели больше 🙂
Видимо там настройки такие, чтобы явно выводились нотисы.
Исправьте:
не заметил array_shift… тогда так:
нафига такие вложенные конструкции писать-то? черт ногу сломит..
Иван Будаков, ошибка осталась та же? поменяйте еще
по аналогии, я не заметила, что str_replace встречается два раза в коде
Сергей delphinpro, Daria Motorina, Спасибо, думаю кому-то это однозначно пригодится, сейчас я точно уверен что дело в версии PHP.
Текущая версия PHP: 7.2.24-0ubuntu0.18.04.1
До миграции на VestaCP была 5.6, буду думать как сделать 5.6 на весте)
нафига такие вложенные конструкции писать-то? черт ногу сломит..
Иван Будаков, Честно говоря, я не помню, чтобы поведение было иным в других версиях. array_shift всегда принимала агрумент по ссылке, и туда нельзя было, передавать ничего кроме переменной.
Возможно у вас просто был отключен вывод ошибок. В данном контексте эта ошибка проблем не доставит, если ее просто подавить. Собственно это не ошибка, и даже не предупреждение, а так, уведомление о не совсем некорректном коде.
Error message «Strict standards: Only variables should be passed by reference»
The above code somehow reports the strict standards warning, but this will not:
So when will it report the warning anyway?
6 Answers 6
Consider the following code:
This will generate the following output:
The reason? The test::get_arr() method is not a variable and under strict mode this will generate a warning. This behavior is extremely non-intuitive as the get_arr() method returns an array value.
To get around this error in strict mode, either change the signature of the method so it doesn’t use a reference:
Since you can’t change the signature of array_shift you can also use an intermediate variable:
$instance->find() returns a reference to a variable.
You get the report when you are trying to use this reference as an argument to a function, without storing it in a variable first.
This helps preventing memory leaks and will probably become an error in the next PHP versions.
Your second code block would throw an error if it wrote like (note the & in the function signature):
So a quick (and not so nice) fix would be:
Basically, you do an assignment to a temporary variable first and send the variable as an argument.
The cause of the error is the use of the internal PHP programming data structures function, array_shift() [php.net/end].
The function takes an array as a parameter. Although an ampersand is indicated in the prototype of array_shift() in the manual», there isn’t any cautionary documentation following in the extended definition of that function, nor is there any apparent explanation that the parameter is in fact passed by reference.
Perhaps this is /understood/. I did not understand, however, so it was difficult for me to detect the cause of the error.
Need to be changed into:
The second snippet doesn’t work either and that’s why.
array_shift is a modifier function, that changes its argument. Therefore it expects its parameter to be a reference, and you cannot reference something that is not a variable. See Rasmus’ explanations here: Strict standards: Only variables should be passed by reference
Well, in obvious cases like that, you can always tell PHP to suppress messages by using «@» in front of the function.
It may not be one of the best programming practices to suppress all errors this way, but in certain cases (like this one) it comes handy and is acceptable.
Why am I getting «Only variables should be passed by reference» error?
Check out this code:
Getting this notice:
Only variables should be passed by reference
4 Answers 4
This array is passed by reference because it is modified by the function. This means you must pass it a real variable and not a function returning an array because only actual variables may be passed by reference.
You should do this instead:
The function end() expects a real variable and not a function returning an array, but if you put the function return inside double parentheses PHP does not report a strict standards notice:
Do it in two lines:
Functions like end() will affect the variable and change their values if they’re supposed to, and as all of us know, it means Pass by Reference! But this kind of passing needs tendency, we can’t just push things to them without any care!
Expressions:
That error is just a kind of strict error at your case and not a fatal one! well you know that PHP is a strict programming language. But you can disable them manually. That doesn’t change the result.
Some examples on this issue:
Error:
Fatal error: Call-time pass-by-reference has been removed; If you would like to pass argument by reference, modify the declaration of foo() since PHP 5.3.0
We’ve seen it before Strict Standards: Only variables should be passed by reference