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
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
最佳答案

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

7年前 评论
讨论数量: 10

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

7年前 评论
leo

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

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

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

@畅畅 不行的,没法访问

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

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

7年前 评论

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

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

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

7年前 评论

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

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

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

7年前 评论

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

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

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

7年前 评论