所以我在确定如何进行feed风格的mysql调用时遇到了一些麻烦,我不知道它是一个雄辩的问题还是一个mysql问题。我相信这两种情况都有可能,我只是需要一些帮助。
所以我有一个用户并且他们转到他们的供稿页面,在这个页面上它显示来自他们的朋友的东西(朋友投票,朋友评论,朋友状态更新)。所以说我有汤姆,蒂姆和泰勒作为我的朋友,我需要得到他们所有的选票,评论,状态更新。我该怎么做?我有一个Id号码的所有朋友的列表,我有每个事件(投票,评论,状态更新)的表,其中存储了Id以链接回用户。那么我怎样才能一次获得所有这些信息,以便我可以以一种形式在Feed中显示它。
蒂姆评论说“酷”泰勒说“Woot第一次状态更新〜!”
泰勒被评为“有史以来最佳竞争”
编辑@damiani 因此,在进行模型更改后,我有这样的代码,它确实返回正确的行
$friends_votes = $user->friends()->join('votes', 'votes.userId', '=', 'friend.friendId')->orderBy('created_at', 'DESC')->get(['votes.*']);
$friends_comments = $user->friends()->join('comments', 'comments.userId', '=', 'friend.friendId')->orderBy('created_at', 'DESC')->get(['comments.*']);
$friends_status = $user->friends()->join('status', 'status.userId', '=', 'friend.friendId')->orderBy('created_at', 'DESC')->get(['status.*']);
但是我希望它们能够立刻发生,这是因为mysql按顺序排序数千条记录比使用3个列表,将它们合并然后再进行操作快100倍。有什么想法吗?
答案 0 :(得分:33)
我确定还有其他方法可以实现这一目标,但一种解决方案是通过查询生成器使用join
。
如果您的表格设置如下:
users
id
...
friends
id
user_id
friend_id
...
votes, comments and status_updates (3 tables)
id
user_id
....
在用户模型中:
class User extends Eloquent {
public function friends()
{
return $this->hasMany('Friend');
}
}
在好友模型中:
class Friend extends Eloquent {
public function user()
{
return $this->belongsTo('User');
}
}
然后,要收集id为1的用户朋友的所有投票,您可以运行此查询:
$user = User::find(1);
$friends_votes = $user->friends()
->with('user') // bring along details of the friend
->join('votes', 'votes.user_id', '=', 'friends.friend_id')
->get(['votes.*']); // exclude extra details from friends table
为join
和comments
表运行相同的status_updates
。如果您希望将投票,评论和status_updates放在一个按时间顺序排列的列表中,则可以将生成的三个集合合并为一个,然后对合并的集合进行排序。
修改强>
要在一个查询中获取投票,评论和状态更新,您可以构建每个查询,然后将结果合并。不幸的是,如果我们使用Eloquent hasMany
关系(see comments for this question来讨论该问题),这似乎不起作用,所以我们必须修改查询以使用where
代替:
$friends_votes =
DB::table('friends')->where('friends.user_id','1')
->join('votes', 'votes.user_id', '=', 'friends.friend_id');
$friends_comments =
DB::table('friends')->where('friends.user_id','1')
->join('comments', 'comments.user_id', '=', 'friends.friend_id');
$friends_status_updates =
DB::table('status_updates')->where('status_updates.user_id','1')
->join('friends', 'status_updates.user_id', '=', 'friends.friend_id');
$friends_events =
$friends_votes
->union($friends_comments)
->union($friends_status_updates)
->get();
此时,我们的查询有点毛茸茸,因此与多余的关系和一个额外的表(如下面的DefiniteIntegral建议)可能是一个更好的主意。
答案 1 :(得分:3)
可能不是你想听到的,但是“feed”表对于这种交易来说将是一个伟大的中间人,为你提供一种非规范化的方式,通过多态关系转向所有这些数据。
你可以像这样构建它:
<?php
Schema::create('feeds', function($table) {
$table->increments('id');
$table->timestamps();
$table->unsignedInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->morphs('target');
});
像这样构建Feed模型:
<?php
class Feed extends Eloquent
{
protected $fillable = ['user_id', 'target_type', 'target_id'];
public function user()
{
return $this->belongsTo('User');
}
public function target()
{
return $this->morphTo();
}
}
然后用类似的东西保持最新:
<?php
Vote::created(function(Vote $vote) {
$target_type = 'Vote';
$target_id = $vote->id;
$user_id = $vote->user_id;
Feed::create(compact('target_type', 'target_id', 'user_id'));
});
你可以使上面更通用/更健壮 - 这只是为了演示目的。
此时,您的Feed项目很容易一次检索:
<?php
Feed::whereIn('user_id', $my_friend_ids)
->with('user', 'target')
->orderBy('created_at', 'desc')
->get();