调用前检查某项是否为函数

时间:2019-06-25 16:33:40

标签: php

我有一堂课,看起来像这样:

<?php

namespace App\Http\Controllers;

use Exception;
use Illuminate\Http\Request;

class FormatAddressController extends Controller
{
    public function __construct()
    {
        $this->middleware(['api-auth']);
        $this->middleware(['api-after']);
    }

    public function format(Request $request) {
        // TODO first, get customer settings to see what functions to run, and how to run them
        // but, assume that the settings come as an array where the key is the function name
        // and the value is one of NULL, false, or settings to pass through to the function
        $settings = ['isoAndCountry' => true, 'testFunc' => ['testSetting' => 'test setting value']];

        $address = $request->input('address');

        $errors = [];

        foreach ($settings as $funcName => $funcSettings) {    
            try {
                $address = $this->$funcName($funcSettings, $address); // every function has to return the modified address
            } catch(Exception $e) {
                $errors[$funcName] = $e;
            }

        }

        return response()->json([
            'address' => $address,
            'errors' => $errors
        ]);
    }

    public function isoAndCountry($settings, $address) {
        // TODO

        return $address;
    }
}

现在,当我通过上面定义的设置循环调用此函数isoAndCountry时,它将起作用!效果很好。

但是我尝试遵循this thread并检查is_callable并...错误:

            if (is_callable($this->$funcName)) {
                try {
                    $address = $this->$funcName($funcSettings, $address); // every function has to return the modified address
                } catch(Exception $e) {
                    $errors[$funcName] = $e;
                }
            }

如何检查它是否可调用?为什么这行不通?

4 个答案:

答案 0 :(得分:2)

也许这也可以解决问题:

 if(method_exists($this,$funcName)){ ... }

答案 1 :(得分:2)

您必须在此处使用<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Youtube video</title> </head> <body> <iframe width="560" height="315" src="https://www.youtube.com/embed/kw4tT7SCmaY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen> </iframe> </body> </html>来检查该方法是否确实存在于类中。

method_exists

foreach ($settings as $funcName => $funcSettings) { if (method_exists($this, $funcName)) { $this->$funcName($funcSettings, $address); } } 在您的情况下不起作用的原因是因为Laravel控制器具有is_callable魔术方法,该方法可以处理未定义的方法,因此在任何不存在的方法上运行__call都会返回是的。

以下面的类为例:

is_callable

class A { public function __construct() { var_dump(is_callable([$this, 'testFunc'])); } } 的输出为new A。但是,如果将以下内容添加到该类中:

false

现在public function __call($name, $arguments) { // } 的输出将返回var_dump

您可以在此处阅读有关我刚才提到的true场景的更多信息:https://www.php.net/manual/en/function.is-callable.php#118623

有关__call的更多信息:https://www.php.net/manual/en/language.oop5.overloading.php#object.call

答案 2 :(得分:1)

您可以使用

if (is_callable([$this, $funcName])) { ...

相反。

is_callable($this->$funcName)编写代码的方式是,在$funcName上查找一个名为$this的属性(可能不存在),并检查是否可调用。如果使用该数组语法,它将代之以命名方法。


在这种情况下使用起来可能更简单

if (method_exists($this, $funcName)) {

由于您正在同一对象的另一种方法中使用它,因此,如果该方法存在,它应该是可调用的。

答案 3 :(得分:0)

您需要区分类属性和方法。例如在此类中:

class A {
    private $foo = null;

    public function getFoo() {
        return $this->foo;
    }
}
  • private $foo是属性,可以由property_exists()
  • 检查
  • public function getFoo()是方法,可以由method_exists()检查

https://www.php.net/manual/en/function.property-exists.php
https://www.php.net/manual/en/function.method-exists.php

我认为$this->$funcName仅适用于属性。