Home » Php » Redefining PHP function?

Redefining PHP function?

Posted by: admin April 23, 2020 Leave a comment

Questions:

If I have a function:

function this($a){
   return $a;
}

If I wanted to redefine the function, would it be as simple as rewriting it?

function this($a, $b){  //New this function
   return $a * $b;
}
How to&Answers:

Nope, that throws an error:

Fatal error: Cannot redeclare foo()

The runkit provides options, including runkit_function_rename() and runkit_function_redefine().

Answer:

If you mean overloading in a Java sense, then the answer is no, this is not possible.

Quoting the PHP manual on functions:

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

You could use the runkit extension but usage of runkit in production scenarios is generally considered doubtful practice. If you want to exchange algorithms at runtime, have a look at the Strategy pattern or Anonymous functions instead.

If by redefine you mean add to an existing userland function, refactor, substitute or rewrite, then yes: it is as simple as you’ve shown. Just add the additional code to the function, but make sure you set a default for backwards compatibility.

Another option would be to use http://antecedent.github.io/patchwork

Patchwork is a PHP library that makes it possible to redefine user-defined functions and methods at runtime, loosely replicating the functionality runkit_function_redefine in pure PHP 5.3 code, which, among other things, enables you to replace static and private methods with test doubles.

Answer:

You can’t redefine or ‘undefine’ a function in PHP (without resorting to third-party modules). However, you can define a function conditionally.

So, if you know function A can be defined elsewhere, but not always, you can wrap it like this:

if (!function_exists('A')) {
    function A() {
        // default A implementation
    }
}

Then you only need to make sure the implementation you want is encountered first:

function A() {
    // another A implementation
}

Answer:

I’ve got a library of functions that sometimes I just don’t want invoked while I’m testing (typically database updates). If I have, for example, a few different db update functions that are all over the code. instead of commenting out the code, I just create a special class (e.g. class foo {}). Define a global variable (e.g., $DEBUG) and a dummy function (e.g., function dummy {}).
Inside foo define all the (public static) functions you need to mimic as

$fn = isset($DEBUG) ? ‘dummy’ : ‘real function’;
return call_user_func_array($fn,func_get_args());

Plus you have the advantages of now doing other things, like logging the calls and parameters.

Then simply replace all your calls to real_function(…) with foo::real_function(…). Usually just a simple search/replace (or leave it there; depending on what’s going on in the function and how often it’s getting called the overhead may be irrelevant).

Answer:

I have good news and bad news.

The good news

It is possible (link(s) below).

The nadnews

There are 2 bad news:

By default, only userspace functions may be removed, renamed, or modified. In order to override internal functions, you must enable the runkit.internal_override setting in php.ini.

And the second bad news: You havbe to sacrifice code readability.

Example:

<?php
function this($a){
   return $a;
}

echo this(0);

$f_name = 'this';
$f_args = '$a';
$f_code = 'return $a*$b;';
runkit_function_redefine($f_name, f_args, f_code);

echo this(1,3);

Oh, and one more thing, using this as a name for a function may create confusion, due to the methods of a object of a class being able to use this.something to reffer to the variable something that is in the method and have the same name as the variable something from the object itself. Here is an example

<?php
class theclass{
  $a = 'a';
  function a($a){
    echo $a;
    $a = this.$a;
  }
}
theclass $object = new theclass();
$object -> a('b'); // will echo: ab

Answer:

You can’t have both functions declared at the same time, that will give an error.

Answer:

You can’t redeclare it. If your question is just about overloading that example, how about:

function this($a, $b=1)
{
    return $a * $b;
}

Answer:

Setting an appropriate default to any new arguments that you add might help for backwards compatibility, i.e.:

function this($a, $b=1){  //New this function with a sane default.
    return $a * $b;
}

I also recommend, for clarity, generally avoiding using this for function/variable names.