美文网首页
PHP instanceof 使用注意事项

PHP instanceof 使用注意事项

作者: zshanjun | 来源:发表于2017-03-24 17:30 被阅读159次

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


    参考网站:

    相关文章

      网友评论

          本文标题:PHP instanceof 使用注意事项

          本文链接:https://www.haomeiwen.com/subject/dgmfottx.html