Laravel 在 with 查询中只查询个别字段

刚答了一篇帖子, 算比较常用的技巧,整理一下分享出来。

在使用 Laravel 的关联查询中,我们经常使用 with 方法来避免 N+1 查询,但是 with 会将目标关联的所有字段全部查询出来,对于有强迫症的我们来说,当然是不允许的。

这时候我们可以使用下面的技巧在使用 with 时只查询目标关联的部分字段:

$topics = Topic::limit(2)->with(['user'=>function($query){
   $query->select('id','username');
}])->get();

但是每次查询都写得这么繁琐真的好么?不如利用 Laravel 的范围查询将其封装起来:

在 Model 基类中定义一个范围查询(或者使用 Trait)

class BaseModel extends \Eloquent{
    public function scopeWithOnly($query, $relation, Array $columns)
    {
        return $query->with([$relation => function ($query) use ($columns){
            $query->select(array_merge(['id'], $columns));
        }]);
    }
}

在我们普通的 Model 类都继承基类:

class Topic extends BaseModel{
    public function user()
    {
        return $this->belongsTo('User');
    }
}

然后使用就很方便了:

$topics = Topic::limit(2)->withOnly('user', ['username'])->get();
本帖已被设为精华帖!
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 25

如果关联关系是多层嵌套需要怎么才能实现,例如 ...->with('product.productImg')->get()

2年前
小怪兽

就是会不会感觉有点多余,因为我感觉你这样在查的时候也是把要查的字段以数组形式放进去 跟外面写貌似都一样的性质,还是说我理解错了呢

2年前

@ruanqi with查询结果空是因为你的查询字段不包含你的关联字段, 就比如 拿ID关联的话, 你就得 select() 里必须包含ID, 要么就返回空

2年前

@2016 为啥没有包含关联字段就会为空呢,文档上没找到说明

1年前

我想问下 为什么我 的是为空呢 ?
$faqs = Faq::limit(5)
->withOnly('reply', ['id', 'content'])
->get();

1年前

是按你说那样在baseModel 中添加了你的那个方法

1年前

我直接用with 时查询了所有

1年前

我也觉得多余了。
不过可能安全性能好点?比如缺省某些字段。

我改写了一下,因为我主键名不为 id,所以楼主那样就会 null 了。

    public function scopeWithOnly(object $query, string $relation, array $columns)
    {
        return $query->with([$relation => function ($query) use ($columns) {

            if (count($columns) == 1) {
                $columns = array_merge(['id'], $columns);
            }
            $query->select($columns);
        }]);
    }
3个月前

请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!

社区文档:

将托管在 packagist.org 和 github.com 的扩展包使用国内 CDN 加速
GitHub Laravel 扩展包 TOP 250
速查表方便快速查询框架功能,支持手机访问,支持中英文版本
Laravel 中文文档,由社区用户翻译和维护,将会保持一直更新
此文档的目的,就是为了提高技术团队的凝聚力、一致性和生产效率。
开发环境的部署,开发者工具的选择,适用于 Mac 和 Windows。
浓缩过后的精华
Laravel Nova 后台管理面板文档的中文翻译
Lumen 中文文档,由社区用户翻译和维护,将会保持一直更新
Laravel 下知名扩展包 Dingo API 的中文文档,Laravel API 开发必知必会