2

Long story short I'm working with a legacy codebase that makes heavy use of PHP's built-in call_user_func_array function. I'm trying to get it to work with PHP 5.3 (upgrading from 5.2), but have run into the issue described here (in the "Passing non-arrays" section):

http://sixohthree.com/1486/migrating-to-php-5-3-call_user_func_array

In a nutshell, the problem is that between PHP versions 5.2 and 5.3 the bevavior of this function was changed so that it basically does nothing and returns NULL if the second parameter is not a proper array/object/associative array. 5.2 did not do this, and as such the codebase I'm working with makes no effort to ensure that it passes a parameter of the correct type. This causes problems.

To fix it I could follow the instructions in the blog post and hunt down every single call_user_func_array call in the codebase and patch them up, but that would be extremely tedious. Alternately, I noticed that PHP has a built-in override_function API call that can be used to override the built-in functions. That's handy, but what I want to do is more like extending the built-in function.

Ideally what I'd like is to be able to replace the implementation of call_user_func_array with something roughly like:

function call_user_func_array($method, $params) {
    $params = is_array($params) ? $params : array($params);
    return old_call_user_func_array($method, $params);
}

...where old_call_user_func_array is the built-in call_user_func_array function.

Is this possible, and if so, how?

aroth
  • 54,026
  • 20
  • 135
  • 176
  • 2
    Since the code does not conform to the documented API it is essentially broken, you'll need to fix every instance of that function anyway at some point instead of layering patches upon patches. I can see that you may need a temporary workaround though, so +1 anyway. :) – deceze Jan 11 '12 at 04:40
  • possibly duplicate of http://stackoverflow.com/questions/4725194/php-override-existing-function – Nazariy Jan 11 '12 at 04:44
  • 1
    @Nazariy - That thread does not deal with preserving the old function. Read the OP's question carefully. – Joseph Silber Jan 11 '12 at 04:49
  • What deceze said. Your code is *broken*, the solution is to *fix your code*, not try to change the behaviour of PHP so it accepts your broken code and does something unexpected with it. That is the road to unmaintainable nightmarish ruin. The only solution is to find and fix every instance, regardless of how tedious you think it is. `call_user_func_array` is extremely easy to grep for. – user229044 Jan 11 '12 at 04:57
  • Why not the other way round? Add your override function as `your_call_user_func_array` and search&replace all other references to the built-in (as temporary measure). – mario Jan 11 '12 at 05:01
  • Given the situation of your codebase, this doesn't sound like much of an "upgrade" :-\ – atxdba Jan 11 '12 at 05:16
  • @meagar: It's not really "my" code, it's someone else's code that I'm moving to a new server. I understand that "fix the code" is the pedantically correct answer, but I'd rather have a practical and expedient solution. And don't the stewards of PHP deserve to be chastised at least a little for introducing a breaking change to a built-in function as part of a minor version upgrade? "Backwards compatibility" and all that. atxdba: Yep, the main problem is that there doesn't seem to be a simple way to downgrade from PHP 5.3 to PHP 5.2 on the new server. That would also solve the problem. – aroth Jan 11 '12 at 06:22

3 Answers3

5

You can use rename_function which is also in the APD extension so you should already have it if you have override_function installed:

rename_function('call_user_func_array', 'old_user_func_array');

function call_user_func_array($method, $params) {
    $params = is_array($params) ? $params : array($params);
    old_call_user_func_array($method, $params);
}
Paul
  • 139,544
  • 27
  • 275
  • 264
  • Thanks, this worked, although I found that I had to specify the new function definition using a call to `override_function()` (passing the original function name as the name of the function to override). – aroth Jan 11 '12 at 07:01
1

Hi your question is actually answered in the third or fourth comment posting in the online PHP documentation. There is often very useful information and examples in the comments section (mind you there is also somtimes stuff that is patently incorrect!) I've copied the relevant portion here for your convenience:

... if you use rename_function to rename the original function to a third name, then call the third name in the OVERRIDING function, you will get the desired effect:

rename_function('strlen', 'new_strlen');

override_function('strlen', '$string', 'return override_strlen($string);');

function override_strlen($string){ return new_strlen($string);}

Murray McDonald
  • 631
  • 4
  • 5
0

or you can put your code in a namespace:

namespace Phpoverride
{
    function call_user_func_array($method, $params) {
        return \call_user_func_array($method, $params);
    }
}

http://php.net/namespaces