20

You can do this in Python, but is it possible in PHP?

>>> def a(): print 1
... 
>>> def a(): print 2
... 
>>> a()
2

e.g.:

<? function var_dump() {} ?>
Fatal error: Cannot redeclare var_dump() in /tmp/- on line 1
gak
  • 32,061
  • 28
  • 119
  • 154

6 Answers6

13

This is a bit late, but I just want to point out that since PHP 5.3, it is actually possible to override internal functions without using a PHP extension.

The trick is that you can redefine an internal PHP function inside a namespace. It's based on the way PHP does name resolution for functions:

Inside namespace (say A\B), calls to unqualified functions are resolved at run-time. Here is how a call to function foo() is resolved:

  1. It looks for a function from the current namespace: A\B\foo().
  2. It tries to find and call the global function foo()
Silviu G
  • 1,241
  • 10
  • 31
9

No, it is not possible to do this as you might expect.

From the manual:

PHP does not support function overloading, nor is it possible to undefine or redefine previously-declared functions.

HOWEVER, You can use runkit_function_redefine and its cousins, but it is definitely not very elegant...

You can also use create_function to do something like this:

<?php
$func = create_function('$a,$b','return $a + $b;');
echo $func(3,5); // 8
$func = create_function('$a,$b','return $a * $b;');
echo $func(3,5); // 15
?>

As with runkit, it is not very elegant, but it gives the behavior you are looking for.

Tim Lytle
  • 17,549
  • 10
  • 60
  • 91
Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
  • You said it twice, but Why is it "not very elegant"? – Pacerier Mar 25 '15 at 05:29
  • @Pacerier: Well, for starters, it is a bit of a code smell to be wanting to do this to begin with, and it is definitely going to throw off anyone coming behind you to look at your code, but if you get past that you're having to type the function code as a string argument in both cases, which is unsightly for anything but the shortest functions. – Paolo Bergantino Mar 25 '15 at 20:38
  • Surely we are at least on PHP 5.3, no one does String anymore, the function code can be supplied as an anonymous function. – Pacerier Mar 29 '15 at 02:52
  • @Pacerier: I've never used this function, and this answer was written 6 years ago, and I don't really care to look into it, but the manual says only a string is accepted as an argument for it. Anonymous functions could/should be used to solve similar problems in >5.3, though. – Paolo Bergantino Mar 29 '15 at 18:43
5

I realize this question is a bit old, but Patchwork is a recently-released PHP 5.3 project that supports redefinition of user-defined functions. Though, as the author mentions, you will need to resort to runkit or php-test-helpers to monkey-patch core/library functions.

jmikola
  • 6,892
  • 1
  • 31
  • 61
1

As jmikola mentioned, Patchwork is a good solution if you want to add code to a function.

Here's an article about how it works: http://phpmyweb.net/2012/04/26/write-an-awesome-plugin-system-in-php/

It comes with some sample code. I think the phpmyweb version uses a slightly better code, because he doesn't use eval()'d code, unlike patchwork. You can cache opcodes when using eval().

Vivendi
  • 20,047
  • 25
  • 121
  • 196
  • why do you need to worry about opcode caches when you're unit testing? Or what... you're using monkey patching for something other than testing?? in that case you have bigger problems than `eval()` to worry about. – Spudley May 14 '12 at 20:13
  • 1
    @Spudley Obviously the article i posted isn't aimed towards Unit Testing (hence the title "Write an awesome plugin system"). He's just showing another way to create a plugin architecture. And he also says that he just wants to show another way of creating such an architecture. Ofcourse, it's up for discussion if its a good way. Although i don't see any problems with it. --- What 'problems' are you taling about? Like the author said, opcode caching shouldn't be a problem since eval() isn't used at all (unlike patchwork). – Vivendi May 15 '12 at 08:52
  • @Vivendi, Does patchwork use the runkit functions internally? – Pacerier Apr 07 '15 at 14:36
  • 1
    @Pacerier No, it uses the `streamWrapper` class. With that you can basically rewrite included source files before they are parsed by the PHP interpreter. – Vivendi Apr 08 '15 at 14:35
  • @Vivendi, Why does it say [*"This is NOT a real class"*](http://php.net/manual/en/class.streamwrapper.php)? – Pacerier Apr 11 '15 at 17:15
  • @Pacerier Because you cannot instantiate the `StreamWrapper` class. You can only override it by *registering* your own implementation of the `streamWrapper` class by using `stream_wrapper_register`. You know what methods you can override because PHP tells you what methods are available from the link you posted.. – Vivendi Apr 15 '15 at 08:37
1

Kind of. See http://dev.kafol.net/2008/09/php-redefining-deleting-adding.html.

Sophie Alpert
  • 139,698
  • 36
  • 220
  • 238
0

The accepted answer is excellent!!! I will just add,that you can put your codes in Namespace brackets and then the default GLOBAL-SPACE is resetted.

some other ways:

1) rename_function($old_name,$new_name)

2) override_function($old_name, $parameters, $new_func)

and rarely used:

3) runkit_function_rename(...)

4) runkit_function_redefine(...)

Community
  • 1
  • 1
T.Todua
  • 53,146
  • 19
  • 236
  • 237