[php] Is it possible to overwrite a function in PHP

Can you declare a function like this...

function ihatefooexamples(){
  return "boo-foo!";
};

And then redeclare it somewhat like this...

if ($_GET['foolevel'] == 10){
  function ihatefooexamples(){
    return "really boo-foo";
  };
};

Is it possible to overwrite a function that way?

Any way?

This question is related to php function redeclaration

The answer is


Monkey patch in namespace php >= 5.3

A less evasive method than modifying the interpreter is the monkey patch.

Monkey patching is the art of replacing the actual implementation with a similar "patch" of your own.

Ninja skills

Before you can monkey patch like a PHP Ninja we first have to understand PHPs namespaces.

Since PHP 5.3 we got introduced to namespaces which you might at first glance denote to be equivalent to something like java packages perhaps, but it's not quite the same. Namespaces, in PHP, is a way to encapsulate scope by creating a hierarchy of focus, especially for functions and constants. As this topic, fallback to global functions, aims to explain.

If you don't provide a namespace when calling a function, PHP first looks in the current namespace then moves down the hierarchy until it finds the first function declared within that prefixed namespace and executes that. For our example if you are calling print_r(); from namespace My\Awesome\Namespace; What PHP does is to first look for a function called My\Awesome\Namespace\print_r(); then My\Awesome\print_r(); then My\print_r(); until it finds the PHP built in function in the global namespace \print_r();.

You will not be able to define a function print_r($object) {} in the global namespace because this will cause a name collision since a function with that name already exists.

Expect a fatal error to the likes of:

Fatal error: Cannot redeclare print_r()

But nothing stops you, however, from doing just that within the scope of a namespace.

Patching the monkey

Say you have a script using several print_r(); calls.

Example:

<?php
     print_r($some_object);
     // do some stuff
     print_r($another_object);
     // do some other stuff
     print_r($data_object);
     // do more stuff
     print_r($debug_object);

But you later change your mind and you want the output wrapped in <pre></pre> tags instead. Ever happened to you?

Before you go and change every call to print_r(); consider monkey patching instead.

Example:

<?php
    namespace MyNamespace {
        function print_r($object) 
        {
            echo "<pre>", \print_r($object, true), "</pre>"; 
        }

        print_r($some_object);
        // do some stuff
        print_r($another_object);
        // do some other stuff
        print_r($data_object);
        // do more stuff
        print_r($debug_object);
    }

Your script will now be using MyNamespace\print_r(); instead of the global \print_r();

Works great for mocking unit tests.

nJoy!


A solution for the related case where you have an include file A that you can edit and want to override some of its functions in an include file B (or the main file):

Main File:

<?php
$Override=true; // An argument used in A.php
include ("A.php");
include ("B.php");
F1();
?>

Include File A:

<?php
if (!@$Override) {
   function F1 () {echo "This is F1() in A";}
}
?>

Include File B:

<?php
   function F1 () {echo "This is F1() in B";}
?>

Browsing to the main file displays "This is F1() in B".


You cannot redeclare any functions in PHP. You can, however, override them. Check out overriding functions as well as renaming functions in order to save the function you're overriding if you want.

So, keep in mind that when you override a function, you lose it. You may want to consider keeping it, but in a different name. Just saying.

Also, if these are functions in classes that you're wanting to override, you would just need to create a subclass and redeclare the function in your class without having to do rename_function and override_function.

Example:

rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');

Depending on situation where you need this, maybe you can use anonymous functions like this:

$greet = function($name)
{
    echo('Hello ' . $name);
};

$greet('World');

...then you can set new function to the given variable any time


You could use the PECL extension

but that is bad practise in my opinion. You are using functions, but check out the Decorator design pattern. Can borrow the basic idea from it.


Have a look at override_function to override the functions.

override_function — Overrides built-in functions

Example:

override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');

I would include all functions of one case in an include file, and the others in another include.

For instance simple.inc would contain function boofoo() { simple } and really.inc would contain function boofoo() { really }

It helps the readability / maintenance of your program, having all functions of the same kind in the same inc.

Then at the top of your main module

  if ($_GET['foolevel'] == 10) {
    include "really.inc";
  }
  else {
    include "simple.inc";
  }

short answer is no, you can't overwrite a function once its in the PHP function scope.

your best of using anonymous functions like so

$ihatefooexamples = function()
{
  return "boo-foo!";
}

//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
   return "really boo-foo";
}

http://php.net/manual/en/functions.anonymous.php


No this will be a problem. PHP Variable Functions