前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >对于魔术方法__call,__callStatic 新的认识

对于魔术方法__call,__callStatic 新的认识

作者头像
写PHP的老王
发布2019-10-15 15:39:15
5710
发布2019-10-15 15:39:15
举报
文章被收录于专栏:写PHP的老王写PHP的老王

误解的一般解释

__call方法在对象方法不存在的时候被调用

__callStatic方法在调用对象静态方法不存在的时候被调用

例如

代码语言:javascript
复制

class Car{
    public function __call($method,$params=[]){
        echo "car call\n";
    }
}

(new Car())->color();

class Bus{
    public static function __callStatic($method,$params=[]){
        echo "Bus callStatic\n";
    }
}

Bus::isSale();

特殊情况

其实上面的解释在某些情况下是正确的。但是在一些特殊情形,如果按照这个解释来理解,就会觉得结果不可思议了。

以下面几个例子进行说明。

__call的调用关注的是方法能不能被访问
代码语言:javascript
复制
class Car{
    public function __call($method,$params=[]){
        echo "car call\n";
    }

    public function color(){
        echo "color red\n";
    }

    protected function isRed(){
        echo "yes is Red\n";
    }

    public function checkColor(){
        $this->color();
        $this->isRed();
    }
}
$car = new Car();
$car->color();
$car->isRed();

$car->checkColor();

输出的结果是

代码语言:javascript
复制
color red
car call isRed
color red
yes is Red

从上面可以看出,其实是否调用__call,依赖的是当前调用方能否访问到要调用的函数,如果可以访问到,则直接调用函数,如果不能访问到,则调用魔术方法__call。所以,调用与否关注的是可访问性。

__callStatic关注的是方法能否被静态的方式访问

接下来看另外一个静态调用的例子

代码语言:javascript
复制
class Car{
    public static function __callStatic($method,$params=[]){
        echo "car callStatic\n";
    }

    public function color(){
        echo "color red\n";
    }

    protected function isRed(){
        echo "yes is Red\n";
    }

    public function checkColor(){
        Car::color();
        Car::isRed();
    }
}

Car::color();
Car::isRed();
(new Car())->checkColor();

输出内容是

代码语言:javascript
复制
color red
car callStatic isRed
color red
yes is Red

并且在外部以静态方式调用Car::color伴有Notice级别错误提示,但是内部调用是没有的。

所以,__callStatic关注的是函数在调用位置能否被静态的方式访问到。如果能访问到,则直接执行该方法。如果不能则执行__callStatic方法

__call 与__callStatic同时存在的情况

方法不可访问的时候,具体调用__call,__callStatic方法,依据的并不是调用方式是否是静态调用,而是所在的上下文。如果上下文是在可访问调用对象的对象里,则调用__call,在静态上下文中调用一个不可访问方法时,调用__callStatic

代码语言:javascript
复制
class Car{
    public static function __callStatic($method,$params=[]){
        echo "car callStatic $method\n";
    }

    public  function __call($method,$params=[]){
        echo "car call $method\n";
    }

    public function checkColor(){
        Car::color();
        Car::isRed();
    }
}


$car = new Car();
Car::color();
Car::isRed();

$car->color();
$car->isRed();

(new Car())->checkColor();

输出内容是

代码语言:javascript
复制
car callStatic color
car callStatic isRed
car call color
car call isRed
car call color
car call isRed

从结果看出,外部静态调用color,isRed方法,上下文是静态方式,所以执行的是__callStatic

而在checkColor方法中,调用的上下文处于当前类对象Car当中,即使是以静态方式调用color,isRed,最终执行的是__call方法。

总结

1)__call方法关注方法能否被访问到,而不仅仅是关注是否存在

2)__callStatic方法关注的是方法能否被静态的访问到,而不是关注方法是否存在,是否是静态方法。

3)具体执行__call,__callStatic,是根据调用的上下文。如果处于静态上下文内,则调用__callStatic。如果处于对象的上线文内,则调用__call

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 写PHP的老王 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 误解的一般解释
  • 特殊情况
    • __call的调用关注的是方法能不能被访问
      • __callStatic关注的是方法能否被静态的方式访问
        • __call 与__callStatic同时存在的情况
        • 总结
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档