大怪兽/hasin

Laravel 框架关联 has in 实现

v4.0.0 2024-03-17 07:27 UTC

README

英文 | 中文

LARAVEL HASIN

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Coverage Status Scrutinizer Code Quality Total Downloads

hasin 是一个基于 where in 语法查询 Laravel ORM 关系的 Composer 包,可以在某些业务场景中替换基于 where exists 语法的 has,以获得更高的性能。

安装

简介

Laravel ORM 的关系非常强大,基于关系的查询 has 也为我们提供了许多灵活的调用方法。然而,在某些情况下,has 使用的是 where exists 语法。

例如

// User hasMany Post
User::has('posts')->get();

select * from users where exists (select * from posts where users.id = posts.user_id)

'exists' 是对外部表的循环,然后每次都查询内部表(子查询)。因为内部表的查询索引(内部表效率高,因此可以用作大型表),以及外部表需要遍历多少,是不可避免的(尽量使用小表),因此对于大型内部表使用 exists 可以提高效率。

然而,当 User 有大量数据时,将会有性能问题,所以 where in 语法将大大提高性能。

select * from users where users.id in (select posts.user_id from posts)

'in' 是将外表和内表进行哈希连接,首先查询内表,然后匹配内表的结果与外表,并使用外表的索引(外表效率高,大表可以使用)。大多数内表都需要查询,这是不可避免的。因此,对于大型外表使用 'in' 可以提高效率。

因此,在代码中使用 has(hasMorph)hasIn(hasMorphIn) 应根据 数据量 来决定。

/**
 * SQL:
 * 
 * select * from `users` 
 * where exists 
 *   ( 
 *      select * from `posts` 
 *      where `users`.`id` = `posts`.`user_id` 
 *   ) 
 * limit 10 offset 0
 */
$users = User::has('posts')->paginate(10);

/**
 * SQL:
 * 
 * select * from `users` 
 * where `users`.`id` in  
 *   ( 
 *      select `posts`.`user_id` from `posts` 
 *   ) 
 * limit 10 offset 0
 */
$users = User::hasIn('posts')->paginate(10);

使用示例

hasIn(hasMorphIn) 支持 Laravel ORM 中的所有 关系。调用方式和内部实现与框架的 has(hasMorph) 完全一致。

hasIn

// hasIn
User::hasIn('posts')->get();

// orHasIn
User::where('age', '>', 18)->orHasIn('posts')->get();

// doesntHaveIn
User::doesntHaveIn('posts')->get();

// orDoesntHaveIn
User::where('age', '>', 18)->orDoesntHaveIn('posts')->get();

whereHasIn

// whereHasIn
User::whereHasIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// orWhereHasIn
User::where('age', '>', 18)->orWhereHasIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// whereDoesntHaveIn
User::whereDoesntHaveIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

// orWhereDoesntHaveIn
User::where('age', '>', 18)->orWhereDoesntHaveIn('posts', function ($query) {
    $query->where('votes', '>', 10);
})->get();

hasMorphIn

Image::hasMorphIn('imageable', [Post::class, Comment::class])->get();

嵌套关系

User::hasIn('posts.comments')->get();

测试

composer test

提示:在测试之前,您需要在 phpunit.xml.dist 中配置您的数据库连接。

许可证

MIT