21

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

6 Answers 6

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()
Sign up to request clarification or add additional context in comments.

3 Comments

Most likely, because it was posted nearly four years after the question, and the accepted answer was probably the most relevant one at the time.
I'm still on SO... Accepted!
Well, this isn't really monkey patching. If there is third-party code that is in the global namespace, this trick doesn't work and you can't monkey patch anything. You don't redefine the function, you just create a new one that takes precedence. Kind of like magic methods.
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.

4 Comments

You said it twice, but Why is it "not very elegant"?
@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.
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: 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.
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.

Comments

1

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

1 Comment

The link is dead.
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().

6 Comments

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 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, Does patchwork use the runkit functions internally?
@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, Why does it say "This is NOT a real class"?
|
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(...)

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.