文章資料結構
Post
- id
- title
- body
- vote_count
- comment_count
評論資料結構
Comment
- id
- title
- body
- commentable_id
- commentable_type
- parent_id
- user_id
- first_depth_id 一級評論id
- vote_count
- comment_count
點贊資料結構
Vote
- id
- user_id
- voteable_id
- voteable_type
Post
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
public function votes()
{
return $this->morphMany(Vote::class, 'voteable');
}
Comment
public function commentable()
{
return $this->morphTo();
}
public function parent()
{
return $this->belongsTo(Comment::class,'parent_id');
}
public function children()
{
return $this->hasMany(Comment::class, 'parent_id');
}
public function user()
{
return $this->belongsTo(User::class);
}
public function votes()
{
return $this->morphMany('App\Vote', 'voteable');
}
public function seconds()
{
return $this->hasMany(Comment::class,'first_depth_id');
}
Vote
public function voteable()
{
return $this->morphTo();
}
public function user()
{
return $this->belongsTo(User::class);
}
1直接用模型查詢評論及使用者的資料,資料型別也符合前端的要求
直接用sql去查文章的評論及使用者(不建議),因為用了7條sql
$posts = Post::with(['comments'=>function ($query){
$query->where('parent_id',null)->with(['user','seconds'=>function($query){
$query->with('user','parent.user');
}]);
}])->get();
debug 顯示
返回到前端的資料
2查詢出所有評論及使用者,再去解析資料,返回前端。
該查詢用到三條sql(建議)
$posts = Post::with('comments','comments.user')->get();
$posts = collect($posts->toArray())->map(function ($post){
$nestedKeys = [];
$post['comments'] = array_column($post['comments'], null, 'id');
foreach ($post['comments'] as $key=>$comment){
if(!$parent_id=$comment['parent_id']){
continue;
}
if (array_key_exists($first_depth_id=$comment['first_depth_id'], $post['comments'])) {
if(!isset($post['comments'][$first_depth_id]['seconds'])){
$post['comments'][$first_depth_id]['seconds'] = [];
}
$comment['parent']=$post['comments'][$parent_id];
$post['comments'][$first_depth_id]['seconds'][] = $comment;
$nestedKeys[]=$key;
}else{
$nestedKeys[]=$key;
}
}
foreach ($nestedKeys as $val){
unset($post['comments'][$val]);
}
return $post;
});
debug
返回到前端的資料,可以看到和上方的返回資料是一樣的,而這個只用了三條sql
由於點贊沒有無限極的影響,所以實現起來比較簡單
直接用模型實現
在評論的基礎上加上點贊和點讚的使用者即可(不建議,因為sql增加到12條)
$posts = Post::with(['comments'=>function ($query){
$query->where('parent_id',null)->with(['votes'=>function($query){
$query->with('user');
},'user','seconds'=>function($query){
$query->with(['user','parent.user','votes'=>function($query){
$query->with('user');
}]);
}]);
},'votes'=>function($query){
$query->with('user');
}])->get();
debug
返回的資料
先查出總資料再去解析
在評論的基礎上加個點贊即可,用了7條sql(建議)
$posts = Post::with('comments','comments.user','votes.user','comments.votes.user')->get();
$posts = collect($posts->toArray())->map(function ($post){
$nestedKeys = [];
$post['comments'] = array_column($post['comments'], null, 'id');
foreach ($post['comments'] as $key=>$comment){
if(!$parent_id=$comment['parent_id']){
continue;
}
if (array_key_exists($first_depth_id=$comment['first_depth_id'], $post['comments'])) {
if(!isset($post['comments'][$first_depth_id]['seconds'])){
$post['comments'][$first_depth_id]['seconds'] = [];
}
$comment['parent']=$post['comments'][$parent_id];
$post['comments'][$first_depth_id]['seconds'][] = $comment;
$nestedKeys[]=$key;
}else{
$nestedKeys[]=$key;
}
}
foreach ($nestedKeys as $val){
unset($post['comments'][$val]);
}
return $post;
});
debug 增加的4條sql是不可避免的
返回的資料
總結
一般來說查詢sql的時間,要多於程式解析的時間,所以把需要用到的資料,查詢出來,再去由程式去解析成相應的資料型別,而不要用sql去實現。