mpyw / eloquent-has-by-join
此包已被弃用且不再维护。没有建议的替代包。
将单个结果关系的has()和whereHas()约束转换为join()。
v2.0.2
2022-07-14 19:34 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-non-dependent-subquery: Provides more versatile non-dependent subqueries
README
将has()
和whereHas()
约束转换为join()
,用于单个结果关系。
重要
注意: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-join
动机
假设你有一个以下关系
class Post extends Model { use SoftDeletes; }
class Comment extends Model { use SoftDeletes; public function post(): BelongsTo { return $this->belongsTo(Post::class); } }
如果你使用has()
约束,你的实际查询将包含相关子查询。
$comments = Comment::has('post')->get();
select * from `comments` where exists ( select * from `posts` where `comments`.`post_id` = `posts`.`id` and `posts`.`deleted_at` is null ) and `comments`.`deleted_at` is null
这些子查询可能会导致性能下降。此包提供了Illuminate\Database\Eloquent\Builder::hasByJoin()
宏来解决这个问题:你可以轻松地将相关子查询转换为简单的JOIN查询。
$comments = Comment::hasByJoin('post')->get();
select `comments`.* from `comments` inner join `posts` on `comments`.`post_id` = `posts`.`id` and `posts`.`deleted_at` is null where `comments`.`deleted_at` is null
API
签名
Illuminate\Database\Eloquent\Builder::hasByJoin(string|string[] $relationMethod, ?callable ...$constraints): $this
参数
$relationMethod
一个返回BelongsTo
、HasOne
或MorphOne
实例的关系方法名称。
Builder::hasByJoin('post')
你可以传递嵌套关系作为数组或点链式语法字符串。
Builder::hasByJoin(['post', 'author'])
Builder::hasByJoin('post.author')
你可以使用"as"
语法提供表别名。
Builder::hasByJoin(['post as messages', 'author as message_authors'])
$constraints
为接受Illuminate\Database\Eloquent\Builder
作为第一个参数的关系提供的额外callable
约束。
Builder::hasByJoin('post', fn (Builder $query) => $query->withTrashed())
第一个闭包对应于post
,第二个闭包对应于author
。
Builder::hasByJoin( 'post.author', fn (Builder $query) => $query->withTrashed(), fn (Builder $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条件 | ❌ | ✅ |
否定条件 | ❌ | ✅ |
计数条件 | ❌ | ❌ |
一对一 |
✅ | ✅ |
一对多 |
❌ | ✅ |
属于 |
✅ | ✅ |
多对多 |
❌ | ✅ |
多态一对一 |
✅ | ✅ |
多态一对多 |
❌ | ✅ |
多态到 |
❌ | ❌ |
多态一对多 |
❌ | ✅ |
多态多对多 |
❌ | ✅ |
通过中间表一对一 |
❌ | ✅ |
通过中间表一对多 |
❌ | ✅ |