在查看laravel源码的时候,看到有如下一段代码:
/**
* Get the registered service provider instance if it exists.
*
* @param \Illuminate\Support\ServiceProvider|string $provider
* @return \Illuminate\Support\ServiceProvider|null
*/
public function getProvider($provider)
{
$name = is_string($provider) ? $provider : get_class($provider);
return Arr::first($this->serviceProviders, function ($key, $value) use ($name) {
return $value instanceof $name;
});
}
当时就有点困惑,然后在tinker连就敲了一下验证,结果陷入更大的迷惑中。。。
下棉代码是这个问题的尝试的心路历程:
>>> use App\Model\Account;
=> null
>>> $account = new Account();
=> App\Model\Account {#1607}
>>> $account instanceof 'App\Model\Account';
PHP Parse error: Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING on line 1
>>> $account instanceof App\Model\Account;
=> true
>>> $a = 'abc';
=> "abc"
>>> $a instanceof 'abc';
PHP Parse error: Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING on line 1
>>> $account instanceof 'App\Model\Account';
PHP Parse error: Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING on line 1
>>> get_class($a);
PHP warning: get_class() expects parameter 1 to be object, string given on line 1
>>> get_class($account);
=> "App\Model\Account"
>>> $name = get_class($account);
=> "App\Model\Account"
>>> $account instanceof $name;
=> true
>>> gettype($name);
=> "string"
>>> $account instanceof "App\Model\Account";
PHP Parse error: Syntax error, unexpected T_CONSTANT_ENCAPSED_STRING on line 1
>>> $account instanceof Account;
=> true
>>> $temp = "App\Model\Account";
=> "App\Model\Account"
>>> $account instanceof $temp;
=> true
其实上面问题的核心是instanceof的用法问题,在网上已经有这样的讨论,我将其粘贴出来:
class MyClass {
public $bar;
public function __construct() {
$this->bar = "Hello World";
}
public function foo() {
return $this->bar;
}
}
$a = new MyClass;
$b = new MyClass;
if($a instanceof get_class($b)) {
echo "Is instance";
} else {
echo "Is NOT instance";
}
//输出
Parse error: syntax error, unexpected '(' in /usercode/file.php on line 19
但是如果,你这样改写:
$x = get_class($b);
if($a instanceof $x) {
echo "Is instance";
} else {
echo "Is NOT instance";
}
//输出
Is instance
答案是因为instanceof并不是函数,只能接受对象(字面量的,不是字符串)或者变量。如果后面接的是函数或者是字符串(字面量的),那肯定是会报错的,本身语法就会有问题。
原讨论的回答如下:
Logically that would be the case, and if instanceof were a function then it would be the actual case. However, instanceof is a language construct operator, not a normal function and for that reason it doesn't play by the same rules.
instanceof does not accept expressions like a normal function would, and because calling a function like get_class is an expression you can't use it with instanceof.
instanceof accepts only two types of arguments. Either a class name (literal, not as a string) or a variable containing a string that is the class name.
Other language constructs like empty and isset function in exactly the same fashion (ie: you can't pass an expression to them either).
Note that you can use the is_a() function if you want to pass the class name as an expression.
参考网站:
网友评论