在查看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.


参考网站:



登陆发表评论