220

Is there any way to easily fix this issue or do I really need to rewrite all the legacy code?

PHP Fatal error: Call-time pass-by-reference has been removed in ... on line 30

This happens everywhere as variables are passed into functions as references throughout the code.

hakre
  • 193,403
  • 52
  • 435
  • 836
bardiir
  • 14,556
  • 9
  • 41
  • 66
  • 1
    Related: [PHP warning: Call-time pass-by-reference has been deprecated](http://stackoverflow.com/q/4665782/2157640) – Palec Dec 26 '14 at 14:30

3 Answers3

353

You should be denoting the call by reference in the function definition, not the actual call. Since PHP started showing the deprecation errors in version 5.3, I would say it would be a good idea to rewrite the code.

From the documentation:

There is no reference sign on a function call - only on function definitions. Function definitions alone are enough to correctly pass the argument by reference. As of PHP 5.3.0, you will get a warning saying that "call-time pass-by-reference" is deprecated when you use & in foo(&$a);.

For example, instead of using:

// Wrong way!
myFunc(&$arg);               # Deprecated pass-by-reference argument
function myFunc($arg) { }

Use:

// Right way!
myFunc($var);                # pass-by-value argument
function myFunc(&$arg) { }
UserBSS1
  • 2,091
  • 1
  • 28
  • 31
  • 9
    Deprecation is since PHP 5.0.0, back that time giving `E_COMPILE_WARNING` level error, for reference: http://www.php.net/manual/en/ini.core.php#ini.allow-call-time-pass-reference – hakre Jun 28 '12 at 22:20
  • 5
    I had this error but needed to remove the & insted of adding to the variable. – Diana Feb 26 '13 at 00:47
  • 2
    I had this used in the old code for an object called event (&$event), and had to remove the ampersand for the error message to disappear. – Natalia Nov 16 '13 at 17:21
  • 1
    in all my years as a developer i've actually never needed to use & on php. never ever. this was exactly what I was looking for. great – Juan Vilar Jun 12 '14 at 00:38
  • 8
    for the people in the comments, note that removing the & may result in unexpected results as any changes to the variable will no longer be shared but will only be visible to the functions local scope. So unless you know what the code does, I'd recommend fixing it as described above instead of just removing the & character – xorinzor Sep 16 '15 at 07:26
8

For anyone who, like me, reads this because they need to update a giant legacy project to 5.6: as the answers here point out, there is no quick fix: you really do need to find each occurrence of the problem manually, and fix it.

The most convenient way I found to find all problematic lines in a project (short of using a full-blown static code analyzer, which is very accurate but I don't know any that take you to the correct position in the editor right away) was using Visual Studio Code, which has a nice PHP linter built in, and its search feature which allows searching by Regex. (Of course, you can use any IDE/Code editor for this that does PHP linting and Regex searches.)

Using this regex:

^(?!.*function).*(\&\$)

it is possible to search project-wide for the occurrence of &$ only in lines that are not a function definition.

This still turns up a lot of false positives, but it does make the job easier.

VSCode's search results browser makes walking through and finding the offending lines super easy: you just click through each result, and look out for those that the linter underlines red. Those you need to fix.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
6

PHP and references are somewhat unintuitive. If used appropriately references in the right places can provide large performance improvements or avoid very ugly workarounds and unusual code.

The following will produce an error:

 function f(&$v){$v = true;}
 f(&$v);

 function f($v){$v = true;}
 f(&$v);

None of these have to fail as they could follow the rules below but have no doubt been removed or disabled to prevent a lot of legacy confusion.

If they did work, both involve a redundant conversion to reference and the second also involves a redundant conversion back to a scoped contained variable.

The second one used to be possible allowing a reference to be passed to code that wasn't intended to work with references. This is extremely ugly for maintainability.

This will do nothing:

 function f($v){$v = true;}
 $r = &$v;
 f($r);

More specifically, it turns the reference back into a normal variable as you have not asked for a reference.

This will work:

 function f(&$v){$v = true;}
 f($v);

This sees that you are passing a non-reference but want a reference so turns it into a reference.

What this means is that you can't pass a reference to a function where a reference is not explicitly asked for making it one of the few areas where PHP is strict on passing types or in this case more of a meta type.

If you need more dynamic behaviour this will work:

 function f(&$v){$v = true;}
 $v = array(false,false,false);
 $r = &$v[1];
 f($r);

Here it sees that you want a reference and already have a reference so leaves it alone. It may also chain the reference but I doubt this.

jgmjgm
  • 4,240
  • 1
  • 25
  • 18