Laravel 5.3 - 在一个查询中提取多态表的数据?
使用多态关系likeable
,我已经在likeable_items
表中设置了authors
和books
作为likeable_type
。Laravel 5.3 - 在一个查询中提取多态表的数据?
下面是型号:
class Like extends Model {
public function likeable(){
return $this->morphTo();
}
}
class Author extends Model {
public function likes(){
return $this->morphMany('App\Like', 'likeable');
}
}
class Book extends Model {
public function likes(){
return $this->morphMany('App\Like', 'likeable');
}
}
我想用一个高效的查询到拉他们都在各自的数据,10分页,这样的事情不工作(我评论的代码以显示每一步需要什么)。
$likeableData =
DB::table('likeable_items')
// We want to fetch additional data depending on likeable_type
->select(['books.title', 'books.author_name', 'book_counts.like_count']) // when likeable_type = 'book'
->select(['authors.name', 'authors.country', 'authors.age', 'author_counts.like_count']) // when likeable_type = 'author'
->leftJoin('books', 'books.id', '=', 'likeable_items.likeable_id') // when likeable_type = 'book'
->leftJoin('book_counts', 'book_counts.book_id', '=', 'likeable_items.likeable_id') // when likeable_type = 'book'
->leftJoin('author_counts', 'author_counts.author_id', '=', 'likeable_items.likeable_id') // when likeable_type = 'author'
// We want to have distinct results, based on unique id of book/author
->distinct()
// We want to order by the highest like_count, regardlress of likeable_type
->orderBy('book_counts.like_count', 'desc') // order by highest like_count when likeable_type = 'book'
->orderBy('author_counts.like_count', 'desc') // order by highest like_count when likeable_type = 'author_counts'
// We want to paginate the mixed results
->paginate(10);
return $likeableData;
如何,我可以得到不同的结果背部的最高喜欢author
/book
通过likes_count
,各自的数据,10分页?
UPDATE:
下面是表模式:
Table: likeable_items
- id
- likeable_id (book_id or author_id)
- likeable_type (book or author)
Table: books
- id
- title
- author_name
Table: book_counts
- book_id
- like_count
Table: authors
- id
- name
- country
- age
Table: author_counts
- author_id
- like_count
你可以从你的Like
模型做到这一点,而不需要与一些子选择的计数表和分组,如:
$likes = Like::select('*')
->selectSub('COUNT(*)', 'total_likes')
->with('likeable')
->whereIn('likeable_type', [Book::class, Author::class])
->groupBy('likeable_type', 'likeable_id')
->orderBy('total_likes', 'desc')
->paginate(10);
然后访问值:
foreach($likes as $likedItem) {
$likedItem->total_likes;
if($likedItem->likeable_type === Book::class) {
// Your book logic here
$likedItem->likeable->title;
$likedItem->likeable->author_name;
} else {
// Your author logic here
$likedItem->likeable->name;
$likedItem->likeable->country;
$likedItem->likeable->age;
}
}
如果你愿意改变架构和具有大于一个查询可能的解决办法是:
更新模式:
Table: likeable_items
- id
- likeable_id (book_id or author_id)
- likeable_type (book or author)
- like_count
Table: books
- id
- title
- author_name
Table: authors
- id
- name
- country
- age
更新型号:
class Like extends Model
{
/**
* @return bool
*/
public function isBook()
{
return ($this->likeable_type === Book::class);
}
/**
* @return bool
*/
public function isAuthor()
{
return ($this->likeable_type === Author::class);
}
}
除您需要book_counts
和author_counts
为您的系统上的一个特殊的逻辑,我只是将它们删除并移动like_count
到likeable_items
。
like_count
是books
和authors
共有的财产,所以我认为这是合理的将它放在likeable_items
。
Querires:
$likes = Like::orderBy('like_count', 'desc')
->paginate(10);
$likeable_id = $likes->pluck('likeable_id');
$books = Book::whereIn('id', $likeable_id)->get()->groupBy('id');
$authors = Author::whereIn('id', $likeable_id)->get()->groupBy('id');
所以,在这一点上得到最佳的10实在是微不足道。 要取数据,我们使用pluck,然后groupBy使用whereIn
。
关于这一点,请考虑,如果你正在使用likeable_items
派遣id
为books
和authors
两个whereIn
将返回你需要的数据。 相反,如果使用likeable_items
只是缓存books
和authors
ID,则可能有一些数据,你不需要。
如何显示内容:
@forelse ($likes as $item)
@if ($item->isBook())
$books[$item->likeable_id][0]->title;
$books[$item->likeable_id][0]->author_name;
@else
$authors[$item->likeable_id][0]->name;
$authors[$item->likeable_id][0]->country;
$authors[$item->likeable_id][0]->age;
@endif
@empty
@endforelse
最后考虑: 使用这种方法,你会: - 改变你的架构和更新模型 - 你不会使用morphTo
, - 你做的1 3次的查询,而不是,但并不复杂 - 你可以直接使用paginate
- 你总是使用id
为辅助查询(其是良好的性能)
唯一的“阴暗面”正如我说的是,你可能有一些内容你不$books
和$authors
需要的情况下,你是不是从likeable_items
调度的ID,但我认为这是一个合理的交易。
你看过你当前方法的sql结果吗?这对我来说看起来效率并不高效 –
这就是我发布的原因,因为我不知道如何做我在评论中的作为一个有效的查询:) – Wonka
您的'Like'模型是否使用'likeable_items'表?你可以发布你正在查询的3个表格的模式吗? –