使用Laravel (Lumen/Eloquent)查询多对多关系和更多数据


Querying many-to-many relation and some more data with Laravel (Lumen/Eloquent)

我有三个表

表1:posts//存储用户的twitter帖子
表2:tags//存储twitter帖子中使用的标签
表3:post_tag//pivot-table

现在,我想要输入一个tag,例如。'yolo',获取所有带有这个标签的帖子。这很简单,我已经这样做了

类职位:

/**
* Get the tags associated with the post
*
* @return 'Illuminate'Database'Eloquent'Relations'BelongsToMany
*/
public function tags()
{
    return $this->belongsToMany('App'Models'Tag')->get(['tag']);
}

类标记:

/**
 * Get the posts associated with the given tag
 *
 * @return 'Illuminate'Database'Eloquent'Relations'BelongsToMany
 */
public function posts()
{
    return $this->belongsToMany('App'Models'Post');
}

访问数据:

/** @var Tag $tag */
try {
    $tag    = Tag::where('tag', urldecode($passedTag))->firstOrFail();
    return response()->json(['posts' => $tag->posts->toArray()]);
} catch (ModelNotFoundException $e) {
    return response()->json(['errors' => 'No query results for: '. $passedTag]);
}

然而,我还想做的是,也得到所有其他已用于该帖子的标签。例如,一个帖子有标签yoloswag。现在,当用户输入yolo时,我希望应用程序显示所有标记为yolo的帖子,但也显示帖子具有的所有其他标签,在本例中为swag。我已经这样做了

/** @var Tag $tag */
try {
    $tag    = Tag::where('tag', urldecode($passedTag))->firstOrFail();
    $posts  = $tag->posts;
    $fData  = [];
    foreach ($posts as $index=>$post) {
        /** @var Post $post */
        $fData[$index] = $post->toArray();
        $fData[$index]['tags'] = $post->tags();
    }
    return response()->json(['posts' => $fData]);
} catch (ModelNotFoundException $e) {
    return response()->json(['errors' => 'No query results for: '. $passedTag]);
}

但是因为我是Laravel (Lumen)的新手,我很确定有一种更快的方法来做它。有什么建议吗?谢谢!:)

可以Eager加载所有需要的关系。它们也将显示在toArray中。

/** @var Tag $tag */
try {
    return response()->json([
        'posts' => Tag::with('posts')->with([
            'posts.tags' => function ($query) {
                $query->addSelect(['tag']);
             }
        ])
        ->where('tag', urldecode($passedTag))
        ->firstOrFail()->posts->toArray()
    ]);
} catch (ModelNotFoundException $e) {
    return response()->json(['errors' => 'No query results for: '. $passedTag]);
}

主动加载意味着,你可以在检索对象本身的时候预加载对象的任何关系。这不仅可以减少查询负载,还可以为您提供所需的所有数据,而无需额外的循环或数据库调用。正如你所看到的,你可以嵌套急切加载,来加载关系的关系- posts.tags

编辑

关系的即时加载将只从相关标签中获取标签列:

'posts.tags' => function ($query) {
    $query->addSelect(['tag']);
}