检查call_user_func_array是否成功执行

时间:2018-02-16 09:12:01

标签: php call-user-func-array

可以使用call_user_func_array动态调用函数或方法。如果调用本身失败,则返回FALSE。此外,call_user_func_array返回被调用的函数或方法的返回值。

因此,当被调用的函数或方法返回FALSE时(例如,参见SO example),该值将被识别为误报。

如何可靠地检查call_user_func_array是否成功执行了函数或方法调用?

编辑:人们倾向于指出is_callable的存在。但这不是在调用方法之前检查方法是否存在,从而避免了可能的错误。实际上在执行call_user_func_array之前,函数调用及其参数和参数类型已经使用Reflection进行验证,以避免Massive Assign attack

documentation提到FALSE返回值,但我看不出如何使用它来检查调用是否成功。

2 个答案:

答案 0 :(得分:3)

您可以明确检查上次通话期间是否发生错误:

error_clear_last();  // since PHP 7, before that you'll need to store and
                     // compare the error state before and after the call

$result = call_user_func_array($foo, $bar);

if ($result === false && error_get_last()) {
    echo 'Failed to call ', $foo;
}

以上是对任何错误的一般性检查,您可能希望更详细地检查上一个错误。它看起来像是:

Array
(
    [type] => 2
    [message] => call_user_func_array() expects parameter 1 to be a valid callback, function 'foo' not found or invalid function name
    [file] => /in/M8PrG
    [line] => 3
)

您可能需要检查message是否与'call_user_func_array() expects parameter 1 to be a valid callback'匹配和/或它引用的行是上面的行。请注意,特别是在PHP版本之间检查消息可能会中断。

另一种方法是在之前检查是否应该回调is_callable

答案 1 :(得分:1)

我将boolean callable转换为void,但会在出错时抛出异常。

这样,您可以捕获异常,并且知道false是否call_user_func_array仅返回其调用失败:

<?php
$booleanCallable = function (... $args): bool {
    foreach ($args as $arg) {
        echo "$arg \n";
    };

    return false;
};

$transformBooleanCallableToVoidThrowingException = function (callable $c): callable {
    return function (... $args) use ($c): void {
        if (false === $c(... $args)) {
            throw new \RuntimeException("the call to the callable failed");
        }
    };
};

try {
    $callable = $transformBooleanCallableToVoidThrowingException($booleanCallable);
    $response = call_user_func_array($callable, [1, 2, 3]);

    if (false === $response) {
        throw new \RuntimeException("call_user_func_array failed");
    }
} catch (\Exception $e) {
    echo $e->getMessage();
}

这将输出提供的参数和错误消息:

1 
2 
3 
the call to the callable failed