Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a PHP callback accept its parameter(s) by reference?

I've tested the following and it works on both PHP 5.2 and 5.3, however, it's not documented anywhere as far as I can see so I'm evaluating its use.

I have a function in a class called isValid, this checks a hash to see if the given value is in the set of allowed values. There are some values that are valid, but deprecated; I'd like my isValid function to update the passed in value to the current one and return true.

That's fine for when I call it myself, however, I'd like to use this method when used as a callback for array_filter too.

Here's a test case, which as expected results in an array with the values 2,3,4,5,6.

<?php
$test = array(1, 2, 3, 4, 5);
echo print_r(array_filter($test, 'maptest'), true);

function maptest(&$value)
{
$value ++;
return true;
}

So StackOverflow: is this allowed, or is it undocumented functionality that may disappear/stop working/cause errors in the future?

like image 572
philjohn Avatar asked Aug 20 '10 14:08

philjohn


2 Answers

Yes, it's allowed.

In this respect, there's nothing special about calling functions through callbacks.

However, your specific example does not illustrate one difficulty. Consider:

function inc(&$i) { $i++; }
$n = 0;
// Warning:  Parameter 1 to inc() expected to be a reference, value given:
call_user_func('inc', $n);

The problem is that you're passing $n to call_user_func and call_user_func doesn't accept values by reference. So by the time inc is called, it won't receive a reference. This isn't a problem with array_filter because it traverses the array directly and can directly pass the variables in the array to the callback function.

You could use call-time pass-by-reference, but this is deprecated and removed from trunk:

function inc(&$i) { $i++; }
$n = 0;
// Deprecated: Call-time pass-by-reference has been deprecated
call_user_func('inc', &$n);

So the best option is to use call_user_func_array instead:

function inc(&$i) { $i++; }
$n = 0;
call_user_func_array('inc', array(&$n));

This function will pass-by-reference the elements that have the is_ref flag set and will pass-by-value the other ones.

like image 159
Artefacto Avatar answered Oct 04 '22 19:10

Artefacto


Except when explicitly noted, I'd say this is fine and acceptable. A callback can be any built-in or user-defined function.

like image 29
Gordon Avatar answered Oct 04 '22 21:10

Gordon