开发者

Can you make a PHP function recursive without repeating its name?

It's always bugged me a recursive function needs to name itself, when a instantiated class can use $this and a static method can use self etc.

Is there a similar way to do this in a recursive function without naming it again (just to cut down on maintenance)?

Obviously I could use call_user_func or the __FUNCTION__ constant but I would prefer something l开发者_Go百科ess ugly.


You can make use of variable functions and declare a variable with the function name at the beginning of you function (or wherever). No need for call_user_func:

function test($i) {
   $__name = __FUNCTION__;
   if($i > 5) {
       echo $i. "\n";
       $__name($i-1);
   }
}

Don't forget that using the real function name is probably more readable for other people :)
(at least provide a comment why you do this)


Update:
As @Alix mentions in his comment, it might be useful to declare $__name as static. This way, the value is not assigned over and over again to the variable.


I don't know why this is ugly:

return call_user_func_array(__FUNCTION__, func_get_args());

Versus:

return call_user_func_array('someFunction', func_get_args());

You would still need to use call_user_func_array() if you're looking to cut down on maintenance (if your functions have [a lot / a different number] of arguments).

Other than that I don't see another way. Also a static method cannot reference itself using self::, only to its class. You would also need to use the magic __METHOD__ constant to do that.


function anyfunc() {
    __FUNCTION__();
}

if used in class:

protected function anymethod() {
    $this->{__FUNCTION__}();
}


For those of you who want to do this within a static method:

forward_static_call(array('self', __METHOD__), $arg1, $arg2, $etc);

This way if the method is renamed you dont have to worry about changing all the recursion calls within it too.


function self(){
  return call_user_func_array(debug_backtrace()[1]['function'], func_get_args());
}

function test($i) {
    if($i) {
        echo "$i<br>\n";
        self($i-1);
    }
}
test(5);


You can simply include the arguments by combining func_get_args() and the Variadic or ... added in 5.6.

As a procedural function

function foo($arg,$arg1) {
    __FUNCTION__(...func_get_args());
}

As a class method:

protected function foo($arg,$arg1,$arg3, $etc) {
    $this->{__FUNCTION__}(...func_get_args());
}

https://www.php.net/manual/en/functions.arguments.php#functions.variable-arg-list

Coincidently this works anytime you want to inject an array of arguments into a method or function...

For example (these are also equivalent)

public function foo($arg,$arg1)
   call_user_func_array([$this, __FUNCTION__], func_get_args());
}

call_user_func_array should be Deprecated in my opinion, because there is no need for it in several ways. Most obvious to me is this.

public function foo($arg,$arg1)
   call_user_func([$this, __FUNCTION__], ...func_get_args());
}

The ... is quite useful (I think it plays well with named arguments, though I haven't tried that yet).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜