laravel下 如何更优雅的实现这个数据查询需求

背景

laravel 版本

5.4

数据表关系

res 资源
tag 标签

资源 和 标签是多对多关系,所以有中间表 res_tag。

问题

我希望取出一个资源列表,要求如下:

  • 最新的5条
  • tag.id in (1,3,5)

笨方法

我用查询构造器,实现这样的SQL语句。

SELECT
    *
FROM
    res
LEFT JOIN res_tag ON res_tag.res_id = res.id
WHERE
    res_tag.tag_id IN (1, 3, 5)

期望答案

laravel 中是否有更优雅的实现方法。

我对更优雅的定义:比如利用ORM的 “关联” 是否能实现?

20171205,追问

非常感谢 @nopainnogain 的解答,我做了如下修改。

代码

knowledge 就是 tag(上文我为了叙述问题,做了简化)

$knowledge = new Knowledge();
$res = $knowledge->res()
    ->whereIn('knowledge_id', $knowledge_ids)
    ->orderBy('created_at', 'desc')
    ->limit(5)->get();

SQL

实际执行的SQL语句,程序自动添加了 knowledge_res.knowledge_id IS NULL 这个查询条件,导致查不出任何数据。(去掉此查询条件,结果能满足需求

SELECT
 * FROM
    `res`
INNER JOIN `knowledge_res` ON `res`.`id` = `knowledge_res`.`res_id`
WHERE
    `knowledge_res`.`knowledge_id` IS NULL
AND `knowledge_id` IN (
    164,
    165,
    166,
    167,
    168,
    169,
    170
)
AND `res`.`deleted_at` IS NULL
ORDER BY
    `created_at` DESC
LIMIT 5

另外,有一事疑惑

回答中代码:资源Model::query()->tags()

生成的SQL: select * from tag inner 资源 ... 这样取出的资源是以 tag 为主的,我希望是资源列表

所以我改为:tagModel::query()->资源()

生成的SQL:select * from 资源 inner join tag ... 也就是上文提供的SQL。

不知道是解答时手误还是我其他环节出了问题。

沧海一幻觉
浏览 437回答 1
1回答

jeck猫

你这是标准的多对多模型关联在你的资源Model里定义个新方法: public function tags() { return $this->belongsToMany('标签Model'); } 然后: 资源Model::query() ->tags() ->whereIn('res_id',[1,3,5]) ->orderBy('create_time','desc') ->limit(5) ->get(); 2017-12-5试试: ResModel::whereHas('knowledge', function ($query) use ($knowledge_ids) { $query->whereIn('knowledge_id', $knowledge_ids); }) ->orderBy('created_at', 'desc') ->limit(5) ->get();
打开App,查看更多内容
随时随地看视频慕课网APP