2

I'm using PHP 5.4.25. Take the following code:

<?php

function works($params=[])
{
    var_dump(is_array($params));
    var_dump($params);

    $params = (array) $params;

    var_dump(is_array($params));
    var_dump($params);

    $params['first_name'] = "Bob";
}

function fails($params=[])
{
    var_dump(is_array($params));
    var_dump($params);

    $params['first_name'] = "Bob";
}

call_user_func_array('works', ['first_name'=>'John', 'last_name'=>'Doe']);
call_user_func_array('fails', ['first_name'=>'John', 'last_name'=>'Doe']);

Results:

bool(false)

string(4) "John"

bool(true)

array(1) {
  [0] =>
  string(4) "John"
}

bool(false)

string(4) "John"

PHP Warning:  Illegal string offset 'name' in /vhosts/site/test.php on line 14
PHP Stack trace:
PHP   1. {main}() /vhosts/site/test.php:0
PHP   2. call_user_func_array() /vhosts/site/test.php:17
PHP   3. fails() /vhosts/site/test.php:17

It appears that the array passed is not a valid array... It shows only the first value of the array and as a string instead of an array... But you can then cast the string as an array and then it works fine.....

The solution is obviously to just cast it as an array at the beginning of the function, but it seems like you shouldn't have to do this. Is this a PHP bug? I can't seem to find any other reports of this.

2
  • To pass an actual array argument into fails: call_user_func_array('fails', [['first_name'=>'John', 'last_name'=>'Doe']]); Commented Aug 8, 2014 at 17:24
  • That is a weird trick. Thank you. Commented Aug 8, 2014 at 17:27

2 Answers 2

6

This is not a bug, call_user_func_array() takes an array, and passes it into a function as individual arguments.

If you have a function do_something($a, $b, $c) you can do call_user_func_array("do_something", array(1, 2, 3)) and it will call do_something(1, 2, 3). If you just need to call the function and pass the array as an argument, you can use call_user_func.

It sounds like you want to do:

call_user_func('works', ['first_name'=>'John', 'last_name'=>'Doe']);

If you insist on using call_user_func_array, I suppose you could do:

call_user_func_array('works', [['first_name'=>'John', 'last_name'=>'Doe']]);

Which is passing an array of arrays, so it will take the single element in the array and pass it as the argument to the function.

Another options, if the method is dynamic, is to simply do something like this:

$method = "works";
$method(['first_name'=>'John', 'last_name'=>'Doe']);
Sign up to request clarification or add additional context in comments.

2 Comments

Interesting. How come I can cast the first argument as an array and get the whole passed array then?
You could json encode or serialize the array and pass it as that, then in your function json decode/unserialze it.
1

Although the original question asked about PHP 5.4.25, in versions since PHP 5.6, the answer can be simplified with the triple dot variable-length argument lists feature.

call_user_func_array('foo', ['a', 'b', 'c']);

function foo(...$params) {
  // $params = ['a', 'b', 'c']
}

http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.