我有一堂课,看起来像这样:
<?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;
}
}
如何检查它是否可调用?为什么这行不通?
答案 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
仅适用于属性。