mpyw/eloquent-has-by-join

此包已被弃用且不再维护。没有建议的替代包。

将单个结果关系的has()和whereHas()约束转换为join()。

v2.0.2 2022-07-14 19:34 UTC

This package is auto-updated.

Last update: 2023-11-21 17:26:23 UTC


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

一个返回BelongsToHasOneMorphOne实例的关系方法名称。

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条件
否定条件
计数条件
一对一
一对多
属于
多对多
多态一对一
多态一对多
多态到
多态一对多
多态多对多
通过中间表一对一
通过中间表一对多