看看 Eloquent 中的 find 方法

在我们的 User 模型中写上这样一个方法

public static function getUserById($id)
{
    return self::find($id);
}

在我们的 routes.php 去是调用以下这个方法

get('/', function () {
    return App\User::getPostById(1);
});

能得到你想要的结果。

如果你使用 IDE,你会发现找不到我们 Model 中的 find 方法,但是我记得在 laravel5.1 之前一直是存在的,忍不住看了一下 5.1 的 5.0 的代码,大概猜到了可能是我们的 eloquent 更新了。

5.0

很简单的就找到了我们的 find 方法

这里细节先留在,在 5.1 的版本中来看看,因为区别几乎没有。

5.1

既然在5.1的 model 中没有找到 find() 这个方法,然后在具体模型又可以去调用这个方法,想必只有一个可能吧

call()callStatic() 这个两个魔术方法

那我们在 model 中去找到 __call(), __callStatic()

可以看到,当触发 __callStatic() 是会去触发 __call()

原来我们使用的 User::find(1) $user = new User;$user->find(1) 就来自于此

如果你愿意,在__call()return 之前随便 dd 以下,然后调用我们的 getUserById() 肯定是会断点的。

increment()decrement() 就不用多说,只是对某个字段进行加减

不过这边这两个方法为什么使用魔术方法来调用就不太清楚了,可以讨论一下。

接着看 newQuery() 这个方法

call_user_func_array([$query, $method], $parameters) 我觉得通过这段代码你都能猜到是调用 $query 这个对象的 find() 方法了。

接着是 newQueryWithoutScopes() 这个方法怎么去实例化我们的 query

$builder = $this->newEloquentBuilder(
    $this->newBaseQueryBuilder()
);

在我们的 newEloquentBuilder() 方法传递一个新的 builder(这个builder与我们的数据库操作层紧密耦合)

/**
 * Create a new Eloquent query builder for the model.
 *
 * @param  \Illuminate\Database\Query\Builder  $query
 * @return \Illuminate\Database\Eloquent\Builder|static
 */
public function newEloquentBuilder($query)
{
    return new Builder($query);
}

传递什么参数,返回什么对象注释都写得很清楚,本着探索的精神还是接着看下去。

Illuminate\Database\Eloquent\Builder 的构造方法

public function __construct(QueryBuilder $query)
{
    $this->query = $query;
}

接来下看如何拿到这个 QueryBuilder 的对象,我们之前的 newBaseQueryBuilder()

中间还是封装了很多细节,连起来就是

  • Query\Builder 封装了底层的数据库操作

  • Eloquent\Builder 依赖上面的 Builder 封装了一系列非常好用的方法

最后你可以看到我们的 Eloquent\Builderfind()

这样看就比较简单了,调用 modelgetQualifiedKeyName() 拿到主键,然后使用 __call 来调用 where() 去查询数据库...

结论

我们的 find() 方法只是被简单的换到了 Eloquent\Builder 这个类中。

如果你多看一些的话,你会发现,和数据库操作更加耦合的一部分方法都被移到了 Eloquent\Builder,这大概也是 Eloquent 的一次重要升级吧。

能力有些,有不好的错误的还请指正。

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 1

譬如 现在有个表是 「products」, getQualifiedKeyName() 返回的是 products.id ,可是我这边只想返回 id,否则查询结果就有错误

6年前 评论

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