mpyw / eloquent-has-by-non-dependent-subquery
此包已被废弃,不再维护。未建议替代包。
将 has() 和 whereHas() 约束转换为非依赖子查询。
v2.0.3
2022-07-14 19:22 UTC
Requires
- php: ^7.3 || ^8.0
- illuminate/database: ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0
- illuminate/support: ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0
Requires (Dev)
- awobaz/compoships: ^2.0.4
- nilportugues/sql-query-formatter: ^1.2.2
- orchestra/testbench: *
- orchestra/testbench-core: ^4.9 || ^5.9 || >=6.6
- phpunit/phpunit: >=9.5
Suggests
- mpyw/eloquent-has-by-join: Provides simple JOIN queries that do not depend optimizers
README
将 has()
和 whereHas()
约束转换为非依赖子查询。
重要
注意:Postgres 的优化器非常智能,涵盖了依赖(相关)子查询的 JOIN 优化。因此,这个库主要针对 MySQL,其优化器性能较差。
注意
更新:MySQL 的优化器也在版本 8.0.16
中更新,包括类似于 PostgreSQL 的优化。 此库不再维护。
要求
- PHP:
^7.3 || ^8.0
- Laravel:
^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0
安装
composer require mpyw/eloquent-has-by-non-dependent-subquery
建议
您可以使用 wimski/laravel-ide-helper-hook-eloquent-has-by-non-dependent-subquery 与 Laravel IDE Helper 一起使用。
动机
假设您有以下关系
class Post extends Model { use SoftDeletes; public function comments(): HasMany { return $this->hasMany(Comment::class); } }
class Comment extends Model { use SoftDeletes; }
如果您使用 has()
约束,您的实际查询将会有 依赖子查询。
$posts = Post::has('comments')->get();
select * from `posts` where exists ( select * from `comments` where `posts`.`id` = `comments`.`post_id` and `comments`.`deleted_at` is null ) and `posts`.`deleted_at` is null
这些子查询可能会导致性能下降。此包提供了 Illuminate\Database\Eloquent\Builder::hasByNonDependentSubquery()
宏来解决这个问题:您可以轻松地将依赖子查询转换为非依赖子查询。
$posts = Post::hasByNonDependentSubquery('comments')->get();
select * from `posts` where `posts`.`id` in ( select `comments`.`post_id` from `comments` where `comments`.`deleted_at` is null ) and `posts`.`deleted_at` is null
API
签名
Illuminate\Database\Eloquent\Builder::hasByNonDependentSubquery(string|string[] $relationMethod, ?callable ...$constraints): $this
Illuminate\Database\Eloquent\Builder::orHasByNonDependentSubquery(string|string[] $relationMethod, ?callable ...$constraints): $this
Illuminate\Database\Eloquent\Builder::doesntHaveByNonDependentSubquery(string|string[] $relationMethod, ?callable ...$constraints): $this
Illuminate\Database\Eloquent\Builder::orDoesntHaveByNonDependentSubquery(string|string[] $relationMethod, ?callable ...$constraints): $this
参数
$relationMethod
一个返回 Relation
实例的关系方法名称,除了 MorphTo
。
Builder::hasByNonDependentSubquery('comments')
您可以通过数组或点链式语法传递嵌套关系。
Builder::hasByNonDependentSubquery(['comments', 'author'])
Builder::hasByNonDependentSubquery('comments.author')
$constraints
为接受 Illuminate\Database\Eloquent\Relation
作为第一个参数的关系提供的额外 callable
约束。
Builder::hasByNonDependentSubquery('comments', fn (HasMany $query) => $query->withTrashed())
如果您从 PHP 8.0 开始使用联合类型,则类型顺序无关紧要。
// This will work Builder::hasByNonDependentSubquery('comments', fn (HasMany|Comment $query) => $query->withTrashed()) // and so will this Builder::hasByNonDependentSubquery('comments', fn (Comment|HasMany $query) => $query->withTrashed())
第一个闭包对应于 comments
,第二个闭包对应于 author
。
Builder::hasByNonDependentSubquery( 'comments.author', fn (HasMany $query) => $query->withTrashed(), fn (BelongsTo $query) => $query->whereKey(123) )
功能比较
功能 | mpyw/eloquent-has-by-join |
mpyw/eloquent-has-by-non-dependent-subquery |
---|---|---|
最低 Laravel 版本 | 5.6 | 5.8 |
可选约束的参数 | Illuminate\Database\Eloquent\Builder |
Illuminate\Database\Eloquent\Relations\* ( Builder 也可以通过指定参数类型接受) |
Compoships 支持 | ✅ | ❌ |
无子查询 | ✅ | ❌ (性能取决于数据库优化器) |
无表冲突 | ❌ (有时需要指定别名) |
✅ |
无列冲突 | ❌ (有时需要使用限定列名) |
✅ |
OR 条件 | ❌ | ✅ |
否定条件 | ❌ | ✅ |
计数条件 | ❌ | ❌ |
HasOne |
✅ | ✅ |
HasMany |
❌ | ✅ |
BelongsTo |
✅ | ✅ |
BelongsToMany |
❌ | ✅ |
MorphOne |
✅ | ✅ |
MorphMany |
❌ | ✅ |
MorphTo |
❌ | ❌ |
MorphMany |
❌ | ✅ |
MorphToMany |
❌ | ✅ |
HasOneThrough |
❌ | ✅ |
HasManyThrough |
❌ | ✅ |