注意:我使用的是 Laravel 5.3。
我有一张桌子,comments
,看起来像这样:
+====+=========+
| id | message |
+====+=========+
| 1 | Hi |
| 2 | World |
+====+=========+
我有第二个表 comment_stats
,它记录每条评论的总投票数,如下所示:
+====+============+=======+
| id | comment_id | votes |
+====+============+=======+
| 1 | 1 | 10 |
| 2 | 2 | 0 |
+====+============+=======+
最后,我有第三个表 comment_votes
,它跟踪每个用户对每条评论的投票,如下所示:
+====+============+=========+=========+
| id | comment_id | user_id | type |
+====+============+=========+=========+
| 1 | 1 | 10 | 0 |
| 2 | 1 | 9 | 0 |
| 3 | 1 | 8 | 1 |
| 4 | 1 | 7 | 2 |
| 5 | 1 | 6 | 1 |
| 6 | 1 | 5 | 5 |
| 7 | 1 | 4 | 3 |
| 8 | 1 | 3 | 3 |
| 9 | 1 | 2 | 1 |
| 10 | 1 | 1 | 0 |
+====+============+=========+=========+
如您所见,其他用户 (comment_votes
) 可以对每条评论进行投票,并且会在 comment_stats
中跟踪总投票数。每张投票都有一个 type
。总共有 6 个可能的 type
(0-5)。
我当前的 Comment.php
类看起来像:
class Comment extends Model
{
protected $with = [
'votes', 'stats'
];
public function votes()
{
return $this->hasMany('App\Vote');
}
public function stats()
{
return $this->hasOne('App\Stat');
}
}
我的 Stat.php
类看起来像:
class Stat extends Model
{
protected $with = [
'topTypes'
];
public function comment()
{
return $this->belongsTo('App\Comment');
}
public function topTypes()
{
// Need to return an array of the top 3 types here
}
}
我的 Vote.php
类看起来像:
class Vote extends Model
{
public function comment()
{
return $this->belongsTo('App\Comment');
}
}
我想检索每条评论的前 3 个投票type
。因此,对于 comment_id = 1
,输出将是 [0, 1, 3]
(作为数组),按此顺序。 0出现3次,1出现3次,3出现两次。如果有平局,它应该得到较低的整数 type
。
我试图让 JSON 看起来像这样,以便 top_types
成为 stats
的一部分:
{
"id": 1,
"message": "Hi",
"stats": {
"id": 1,
"comment_id": 1,
"votes": 10,
"top_types": [0, 1, 3]
}
}
我怎么能做到这一点?所有这些关系都让我发疯。
答案 0 :(得分:0)
获得结果很简单。
$result = app(Comment::class)->with('stats.topTypes')->find(1);
接下来,由于您只需要前 3 种类型而不是全部,请过滤我们的急切加载查询。
$result = app(Comment::class)->with('stats.topTypes', function (Eloquent\Builder $query) {
$query->limit(3);
})->find(1);
如果这将成为该模型的常见用途,您可以考虑将该行为移至 Query Scope。请注意不要在任何模型类中加载过多的业务逻辑。它可能很诱人,但有点反模式,因为这并不是 MVC 的模型层的真正用途。
另一种选择是在 Stat::topTypes()
方法中将您的限制应用于实际关系定义。同样,仅当您确定该关系的所有用例只需要 3 个结果时才执行此操作。您也可以在那里放一个 orderByDesc('createdAt')
,这在呼叫案例中可能更有用。
最后,由于您不想要完整的 Type 模型结果,而只是一个 ID 数组,请记住,嵌套结果将采用 Eloquent\Collection 对象的形式,它是 Suppot\Collection 的子代,可以访问所有相同的花里胡哨。:
$result->stats->topTypes->transform(function (Type $type) {
return $type->getKey();
});