我在我的应用程序的敏感部分工作,我需要确保最小化查询的数量。我可以通过多个连接轻松完成此操作。问题是:有没有办法用美容做到这一点?
Elequent relationships是一个很好的起点,但大多数时候需要多次查询。
此article中使用的急切加载方法看起来更好但仍需要至少2个查询并使用whereIn语句而不是连接。
Article渴望加载的例子:
$users = User::with('posts')->get();
foreach($users as $user)
{
echo $user->posts->title;
}
使用Eager Loading,Laravel实际上将运行以下
select * from users
select * from posts where user_id in (1, 2, 3, 4, 5, ...)
我目前的解决方案是以非意图的方式使用laravel范围。
public static function scopeUser($query) // join users table and user_ranks
{
return $query->join('users', 'users.id', '=', 'posts.user_id')
->join('user_ranks', 'users.rank_id', '=', 'user_ranks.id');
}
public static function scopeGroup($query,$group_id) // join feeds,group_feeds (pivot) and groups tables
{
return $query->join('feeds', 'feeds.id', '=', 'posts.feed_id')
->join('group_feed', 'feeds.id', '=', 'group_feed.feed_id')
->join('groups', 'groups.id', '=', 'group_feed.group_id')
->where("groups.id","=",$group_id);
}
生成的查询如下所示:
$posts = Post::take($limit)
->skip($offset)
->user() // scropeUser
->group($widget->group_id) // scropeGroup
->whereRaw('user_ranks.view_limit > users.widget_load_total')
->groupBy('users.id')
->orderBy('posts.widget_loads', 'ASC')
->select(
'posts.id AS p_id',
'posts.title AS p_title',
'posts.slug AS p_slug',
'posts.link AS p_link',
'posts.created_on AS p_create_on',
'posts.description AS p_description',
'posts.content AS p_content',
'users.id AS u_id',
'users.last_name AS u_last_name',
'users.first_name AS u_first_name',
'users.image AS u_image',
'users.slug AS u_slug',
'users.rank_id AS u_rank',
'user_ranks.name AS u_rank_name',
'user_ranks.view_limit AS u_view_limit'
)
->get();
由于列名冲突,我需要一个巨大的select语句。这工作并产生一个单一的查询,但它远非性感!
有没有更好的方法来处理大型连接查询?
答案 0 :(得分:1)
您可以尝试在范围内实际添加带别名的选择。
注意:这是完全未经测试的
public static function scopeUser($query) // join users table and user_ranks
{
foreach(Schema::getColumnListing('users') as $column){
$query->addSelect('users.'.$related_column.' AS u_'.$column);
}
$query->addSelect('user_ranks.name AS u_rank_name')
->addSelect('user_ranks.view_limit AS u_view_limit');
$query->join('users', 'users.id', '=', 'posts.user_id')
->join('user_ranks', 'users.rank_id', '=', 'user_ranks.id');
return $query;
}
也没有必要使用p_
前缀为帖子列添加别名...但如果您真的想要,请添加另一个范围,并使用addSelect()