PHP 调用静态方法不存在时首先检查方法是否是静态的而不是走__callStatic?

今天在看laravel的Model 类 发现这样一段代码

public static function __callStatic($method, $parameters)
{
      return (new static)->$method(...$parameters);
}

代码的意思是 当我访问不存在的静态方法时,返回当前类的同名的普通方法, 单看这段代码时,感觉没毛病啊,然后我就自己写了下[之前从没用过,只是好奇]。

class A {
    public static function who() {
        echo __FUNCTION__.'=>'.__CLASS__;
    }
    public static function test() {
        self::who();
    }
    public static function __callStatic($method, $parameters)
    {
        return (new static)->$method(...$parameters);
    }
}
class B extends A {
    public function aa(){
    }
    public function  getData(){
        echo __FUNCTION__;
    }
}
B::getData();

然后 php 报出来一段错误

Non-static method B::getData() should not be called statically

提示说这个方法不是静态的,我感觉受到了侮辱,我当然知道不是静态的啊,我想要的是调用父类的__callStatic()方法,然后重新执行到getData()这个方法,然后打印出当前函数的名字啊。然后做了个系列的研究。

发现,当我调用一个静态方法的时候,php先去找这个方法,发现他不是静态的以后立刻抛出错误,停止执行,这个和我期望的完全不一样,如果抛出错误,停止执行了,那我model类的__callStatic()就没有存在的意义了啊。

所以有些不明白,还请各位大佬解释下。

kingofzihua
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

@朕略显ぼうっと萌 设为 public 时,这个方法是公开的,首先外部调用时会找这个方法,再看定义,因为一个类无法实现 static function a 和 function a ,所以你这个方法不属于静态,他肯定会报错,callStaric 是找不到方法时才会触发 ,把 function 设为私有,外部就相当于找不到这个方法了,从而触发 callStaric

6年前 评论
讨论数量: 10

类里面的方法名称只能有一个,不能重复,你定义不了一个静态,一个非静态的同名方法,所以你不管是 :: 还是 -> 都会先找到这个方法,再看这个方法的定义。
不过你可以试试把 function a 设为 private,这样外部就找不到这个方法了,就会触发 __callStatic

6年前 评论
leo

(new static)->$method(...$parameters);

这个是和 __call() 配合使用的

6年前 评论
朕略显ぼうっと萌

@畅畅 不行的,没法访问

6年前 评论
朕略显ぼうっと萌

@leo 同意,刚刚放发现的, 并且B::getData();改成 @B::getData(); 就可以执行了, 我陷入误区了, 首先【PHP 调用静态方法不存在时首先检查方法是否是静态的而不是走callStatic】这个问题确实是有的,如果我在前面加上@就没问题了,但是laravel中的确实是配合**call**来用的, 不能混了,

6年前 评论

@朕略显ぼうっと萌 错了,是把getData 设为 protected 应该就行了

6年前 评论
朕略显ぼうっと萌

@畅畅 额,确实是哎,为啥子?

6年前 评论

@朕略显ぼうっと萌 这是外部找不到此方法,就会触发继承的 callStatic ,但设置为 private 父类是无法调用子类的方法的 protected 是可以允许父类调用子类的

6年前 评论
朕略显ぼうっと萌

@畅畅 这个我知道,为啥public 的时候他会有错误? public的时候他会先判断这个方法是不是静态的,而不是走__callStaric

6年前 评论

@朕略显ぼうっと萌 设为 public 时,这个方法是公开的,首先外部调用时会找这个方法,再看定义,因为一个类无法实现 static function a 和 function a ,所以你这个方法不属于静态,他肯定会报错,callStaric 是找不到方法时才会触发 ,把 function 设为私有,外部就相当于找不到这个方法了,从而触发 callStaric

6年前 评论
朕略显ぼうっと萌

@畅畅 好的,明白了,谢谢

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!