Laravel 里为什么可以用Model::where(),却不能用Model::getTable()

我理解是:

调用 Model::where()
Model 里没有静态方法 where(),于是会触发 __callStatic()
__callStatic() 中会试图去调用实例方法 where()Model 也没有 where(),于是触发 __call()
__call() 中实例化 \Illuminate\Database\Eloquent\Builder,然后调用 Builder 的实例方法 where()

调用 Model::getTable()
Model 里没有静态方法 getTable(),于是会触发 __callStatic()
__callStatic() 中会试图去调用实例方法 getTable()Model 有定义,所以应该直接调用getTable()

但是却报错

Non-static method Illuminate\Database\Eloquent\Model::getTable() should not be called statically, assuming $this from incompatible context


查了一下错误的原因,鸟哥在这篇文章解释了,PHP 的 Calling Scope


问题是,那为什么可以用 Model::where()

守着一只汪
浏览 795回答 4
4回答

qq_笑_17

在Model中,where方法是不存在的,而getTable方法却是存在的。之所以这么说,是php因为兼容性的考虑,在检查方法是否存在的时候,并不会去检查是不是静态方法,只要方法存在,不管是静态还是非静态,都认为是方法存在的,因此就不会调用__callStatic方法了。 这也就造成了调用Model::where的时候,由于where方法是在Illuminate\Database\Eloquent\Builder中定义的,__call将该方法的调用代理到了Builder上,因此可以调用。而getTable方法,则因为是Model中的实例方法,做方法存在性判断的时候发现方法有了,就不会去调用__callStatic,直接对该方法进行静态调用,所有就抛出了 Non-static method IlluminateDatabaseEloquentModel::getTable() should not be called statically, assuming $this from incompatible context

慕标琳琳

因为我们定义的 Model 直接继承于 Eloquent/Model 鸟哥在博客中这样说 因为你在一个有 calling scope 的上下文中采用”静态的形式”调用了一个类的非静态方法所致. 我的理解是你在一个定义了 __callStatic 的类中(如 User)调用非静态方法 User::getTable。 而 where 等方法是在 Builder 类中的,Eloquent/Model 不直接继承 Builder。

噜噜哒

getTable方法在Model里面定义的是非静态方法 public function getTable() 直接调用PHP就会跳出了一个Strict错误。 而调用Model::where的时候,由于where没有在Model里面定义,PHP会找Model里面的__callStatic,将where方法代理到目标类里面。 Model的__callStatic方法注释也解释的很清楚 /** * Handle dynamic static method calls into the method. * * @param string $method * @param array $parameters * @return mixed */ public static function __callStatic($method, $parameters) { $instance = new static; return call_user_func_array([$instance, $method], $parameters); }
打开App,查看更多内容
随时随地看视频慕课网APP