y-lincoln/lumen-hasin

Laravel 框架关系中的“has in”实现

v1.0.0 2021-07-10 06:52 UTC

This package is not auto-updated.

Last update: 2024-09-29 19:47:16 UTC


README

英文 | 中文

# LUMEN HASIN

<a href="https://packagist.org.cn/packages/biiiiiigmonster/hasin"><img src="https://img.shields.io/packagist/dt/biiiiiigmonster/hasin.svg?color=" /></a> 
<a><img src="https://img.shields.io/badge/php-7.1+-59a9f8.svg?style=flat" /></a> 

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

环境

  • PHP >= 7.1
  • lumen >= 5.8 || >= 8.0

安装

composer require y-lincoln/lumen-hasin

简介

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) 应根据 数据量大小 确定

<?php
/**
 * 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();

许可证

MIT