简体   繁体   English

如何使用Laravel Eloquent中的急切加载按键索引返回的数组?

[英]How to index returned array by key with eager loading in Laravel Eloquent?

I'm working on a side project in which we are trying to implement a "like" functionality for user's posts. 我正在开展一个侧面项目,我们正在尝试为用户的帖子实现“喜欢”功能。 We are using Laravel's ORM and we would like to use eager loading to make things easier, I'll outline the issue below. 我们正在使用Laravel的ORM,我们希望使用急切加载来简化操作,我将在下面概述问题。 Some information first, the Post.php Model contains this: 首先是一些信息,Post.php模型包含:

public function likes()
{
    return $this->hasMany('App\Models\PostLike', 'post_id', 'post_id');
}

The PostController.php implementing the API call to load the posts and their likes looked like: 实现API调用以加载帖子及其喜欢的PostController.php看起来像:

$posts = Post::with("likes")->where("group_id", "=", $group_id)->get();

An example JSON response from the posts API might look like this: posts API的示例JSON响应可能如下所示:

[
    {
        "post_id":1,
        "group_id":1,
        "author_id":1,
        "text":"Some text here.",
        "created_at":"2015-08-13 00:15:08",
        "updated_at":"2015-08-13 00:15:08",
        "likes":[
            {"post_id":1,"user_id":1,"updated_at":"2015-08-14 03:05:48"}
        ]
    }
]

The issue with this is that the "likes" are not indexed by the user_id, so you have to search through the array to determine if a user has liked the post or not, it would be much easier to have it indexed by the unique user_id key. 这个问题是“喜欢”没有被user_id索引,所以你必须搜索数组以确定用户是否喜欢这个帖子,用唯一的user_id索引它会容易得多键。 That would yield something like: 这会产生类似于:

[
    {
        "post_id":1,
        "group_id":1,
        "author_id":1,
        "text":"Some text here.",
        "created_at":"2015-08-13 00:15:08",
        "updated_at":"2015-08-13 00:15:08",
        "likes":{
            "1": {"post_id":1,"user_id":1,"updated_at":"2015-08-14 03:05:48"}
        }
    }
]

So the ultimate question is how do we index the eager loading response by one of the columns it returns? 所以最终的问题是我们如何通过它返回的一个列来索引热切的加载响应?

In order to achieve that, you'll need to add extra post-processing step to your code that would index the array by id . 为了实现这一点,您需要为代码添加额外的后处理步骤,以便通过id索引数组。 This is very easy using Collection 's helper method keyBy() . 使用Collection的辅助方法keyBy()非常容易。

What you need is a accessor that would load the relation if needed and reindex the array. 你需要的是一个访问器,它会在需要时加载关系并重新索引数组。 This accessor can be used in different scenarios, even without eagerly loading the relation, that's why it needs to handle relation loading if needed. 这个访问器可以在不同的场景中使用,即使没有急切地加载关系,这就是它需要在需要时处理关系加载的原因。

Adding that method to your Post model should do the trick: 将该方法添加到Post模型应该可以解决这个问题:

public function getLikesAttribute() {
  return $this->getRelationValue('likes')->keyBy('user_id');
}

Custom accessors take priority above relation definitions in cases like that, when botu likes() and getLikesAttribute() exist. 在存在botu likes()getLikesAttribute()的情况下,自定义访问器优先于关系定义。 That's why your accessor will be called when you do $post->likes and will reindex the table. 这就是为什么当你执行$ post-> likes时会调用你的访问者并重新索引表的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM