3

The documentation on call_user_func_array has a note, part of it quoted below

Before PHP 5.4, referenced variables in param_arr are passed to the function by reference, regardless of whether the function expects the respective parameter to be passed by reference. This form of call-time pass by reference does not emit a deprecation notice, but it is nonetheless deprecated, and has been removed in PHP 5.4.

The function drupal_retrieve_form uses call_user_func_array in building the form, and has this comment shortly before the call:

We need to pass $form_state by reference in order for forms to modify it, since call_user_func_array() requires that referenced variables are passed explicitly.

While I haven't hit any serious issues running PHP 5.4, it sounds to me like anything that builds a form and then relies on getting back a modified form_state will break on 5.4. I may not entirely understand what's happening here however.

What are the consequences for Form API of this PHP 5.4 change?

  • The sentence after that says, "Passing by value when the function expects a parameter by reference results in a warning and having call_user_func() return FALSE." I would take it means you cannot pass as reference a value the function expect not passed as reference, such as in the case the function is defined as my_module_form_builder($form, $form_state). – kiamlaluno Jun 30 '12 at 0:12
  • Yes, now that you point it out, and I read it again, that does seem reasonable. – Letharion Jul 1 '12 at 11:13
  • What I find confusing is the other sentence: "Furthermore, this does not apply to internal functions, for which the function signature is honored." It makes the think the function signature us not honored for user functions. I wish somebody answer your question. – kiamlaluno Jul 1 '12 at 11:45
2

No expert, but here's my punt:

Before PHP 5.4, referenced variables in param_arr are passed to the function by reference, regardless of whether the function expects the respective parameter to be passed by reference. This form of call-time pass by reference ... has been removed in PHP 5.4

means

function myfunction($a, $b) {
  $a++;
  $b++;
  print "myfunction($a, $b)\n";
}

$apples = 10;
$bananas = 20;

// PHP < 5.4: $b is passed by reference, not honouring the function signature
call_user_func_array('myfunction', array($apples, &$bananas));
print("apples: $apples, bananas: $bananas\n");
// PHP < 5.4: $apples = 10, $bananas = 21
// PHP >= 5.4: $apples = 10, $bananas = 20 

and

Furthermore, this does not apply to internal functions, for which the function signature is honored.

presumably means (though it seems a bit unnecessary?):

$angle = 1.5;

// Despite passing by reference, there's no chance of $angle changing as the
// function signature's honored for internal functions.
$res = call_user_func('sin', array(&$angle));

Letharion wrote:

it sounds to me like anything that builds a form and then relies on getting back a modified form_state will break on 5.4

It seems to me like this should be fine, in this case at least: we're passing a reference exactly where it's expected by the function signature (I presume this is still the right way to pass by reference where that matches the signature). However if I am right, then any modules with typos in their form hooks like this function MYMODULE_form_alter($form, $form_state, $form_id) will work exactly as expected under PHP < 5.4, but 'suddenly' mess up on 5.4.

@Letharion: in another answer you mention you have 5.4 running: I would've thought something would've exploded by now if it wasn't passing $form_state by reference? But IIUC if the following works as expected in 5.4, then the code you reference should be ok:

function myfunction(&$a) {
  $a++;
  print "myfunction($a)\n";
}

$a = 10;

call_user_func_array('myfunction', array(&$a));
print "a: $a\n";
// We expect a to be 11 the second time for all versions of PHP.

My 2 pennies

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.