好的...这可能会使您的大脑有些扭曲,但请坚持下去。实际定义的方法是_where()。那么 Post::where 和 $post->where 最终是如何调用 _where() 方法的呢?答案是“魔法”。:D
PHP 有这些称为“魔术方法”的东西,它们可以实现一些非常动态的行为。在这种情况下,Laravel 使用 __callStatic() 和 __call() 来处理对未定义方法的调用。这使得可以静态和非静态调用相同的方法。
public static function __callStatic($method, $parameters)
{
// Create a new instance of the called class, in this case it is Post
$model = get_called_class();
// Call the requested method on the newly created object
return call_user_func_array(array(new $model, $method), $parameters);
}
所以基本上 Post::where() 只是 $post = new Post; 的简写。$post->where()
从这里请求转到 __call() ,其中有一组带下划线的方法名称。如果请求的方法在下划线名称列表中,则调用并返回 $this->_method()。
但这还不是全部。Drew 是正确的,因为 'where_in' 返回一个 Query 对象。您熟悉的大多数 ORM 链接方法实际上都是 ORM 查询对象的一部分。这是整个过程。
- 发布::哪里(...)
- Post::__callStatic('where', ... )
- $post->__call('where', ... )
- $query->_call('where', ... )
- $query->_where( ... )
您要扩展的类是模型使用的查询。无法在 __call() 中定义的下划线方法列表中添加另一个方法名称。您必须将 __call() 完整地复制到您的 Query 定义中,以使您的新方法具有该行为。
我在我的项目中实现了这一点,将 Eloquent(Laravel 模型的别名)指向我的扩展版本,使我的所有模型都可以使用扩展的 Query 方法。
// application/libraries/mylib/query.php
namespace MyLib;
class Model extends \Laravel\Model {
// Tell \MyLib\Model to use \MyLib\Query instead of Laravels Query
protected function query()
{
return new \MyLib\Query($this);
}
}
// application/libraries/mylib/query.php
namespace MyLib;
class Query extends \Laravel\Database\Eloquent\Query {
function _my_method() { ... }
function __call() { ... }
}
// application/config/application.php
'aliases' => array(
...
'Eloquent' => 'MyLib\\Model',
...
)
http://php.net/manual/en/language.oop5.magic.php
https://github.com/laravel/laravel/blob/master/laravel/database/eloquent/model.php#L734
https:// github.com/laravel/laravel/blob/master/laravel/database/eloquent/query.php#L274