ahfa92/laravel-relation-joins

添加了通过关系名称进行连接的能力。

1.0.10 2020-12-01 22:00 UTC

This package is auto-updated.

Last update: 2024-09-07 09:33:52 UTC


README

Latest Stable Version Total Downloads Laravel Version Laravel Version Build Status

此包添加了通过关系名称进行连接的能力。

简介

Eloquent没有提供任何连接工具,所以我们一直依赖于基础的查询构建器连接。虽然Eloquent有“存在”的“has”概念,但仍然有需要返回相关实体信息或聚合信息的时候。

我看到了其他一些包试图实现类似的功能。我试图使用其中至少一个,但它们都因为各种原因而不足。让我先解释这个包的功能,你可能就会明白为什么这个包更好(至少对我来说是这样)。

安装

使用Composer

composer require ahfa92/laravel-relation-joins

免责声明:此包仅供快速修复使用!如果您需要稳定的包,请使用以下Composer包!!!

composer require reedware/laravel-relation-joins

版本控制

此包是为最新的Laravel版本构建的,但支持回退到Laravel 5.5。

用法

1. 通过关系执行连接

这正是这个包的全部意义,所以这里有一个基本的例子

User::query()->joinRelation('posts');

这将通过User模型通过posts关系应用连接,自动利用任何查询范围(如软删除)。

你可以对所有的关系类型执行连接(除了MorphTo,因为“has”也不支持它),包括新的“HasOneThrough”关系。此外,你可以使用类似基础查询构建器的语法执行其他类型的连接

User::query()->leftJoinRelation('posts');
User::query()->rightJoinRelation('posts');
User::query()->crossJoinRelation('posts');

2. 连接到嵌套关系

能够通过关系连接的一个亮点是在你必须导航一个复杂的嵌套关系网时。当你试图通过另一个关系连接一个关系时,你可以使用类似于“has”和“with”概念的“点”语法

User::query()->joinRelation('posts.comments');

3. 添加连接约束

这实际上是我认为现有解决方案中很多地方不足的地方。它们要么创建了自定义的“where”子句,要么将查询限制为仅支持某些类型的“where”子句。使用此包,没有已知的限制,添加约束的方法非常直观

User::query()->joinRelation('posts', function ($join) {
    $join->where('posts.created_at', '>=', '2019-01-01');
});

这将添加特定的约束到已经提供的关系约束中,使得使用起来非常方便。这里有一些更多示例

// Disabling soft deletes for only the "Post" model
User::query()->joinRelation('posts', function ($join) {
    $join->withTrashed();
});
// Using a query scope on the "Post" model
User::query()->joinRelation('posts', function ($join) {
    $join->active();
});

4. 通过关系连接

有时你可能想为中间连接添加子句。在某些其他包中,这可能有点棘手(通过尝试自动推断是否应用连接,或者根本不处理这种情况)。

这个包引入了我称之为“通过”连接的概念。本质上,“通过”连接表示“我只想将点符号中的最后一个关系应用到我的查询中”。

这里有一个示例

// Using a query scope on the "Post" model
User::query()->joinRelation('posts', function ($join) {
    $join->where('is_active', '=', 1);
})->joinThroughRelation('posts.comments', function ($join) {
    $join->where('comments.title', 'like', '%looking for something%');
});

第二部分,joinThroughRelation,将只应用comments关系连接,但它将像来自Post模型一样应用。

5. 在循环关系上连接

此包还支持在循环关系上连接,并像“has”概念那样处理它

public function employees()
{
    return $this->hasMany(static::class, 'manager_id', 'id');
}

User::query()->joinRelation('employees');

// SQL: select * from "users" inner join "users" as "laravel_reserved_0" on "laravel_reserved_0"."manager_id" = "users"."id"

显然,如果你想在employees关系上应用约束,这种命名约定并不是你所希望的。这引出了下一个功能

6. 别名连接

你可以像这样为上面的例子添加别名

User::query()->joinRelation('employees as employees');

// SQL: select * from "users" inner join "users" as "employees" on "employees"."manager_id" = "users"."id"

连接不必是环形的,也可以支持别名。以下是一个示例

User::query()->joinRelation('posts as articles');

// SQL: select * from "users" inner join "posts" as "articles" on "articles"."user_id" = "users"."id"

这对于嵌套关系也适用

User::query()->joinRelation('posts as articles.comments as feedback');

// SQL: select * from "users" inner join "posts" as "articles" on "articles"."user_id" = "users"."id" inner join "comments" as "feedback" on "feedback"."post_id" = "articles"."id"

对于需要多个表的关系(例如 BelongsToMany, HasManyThrough 等),别名将应用于远端/非枢轴表。如果您需要为枢轴/通过表设置别名,可以使用双重别名

public function roles()
{
    return $this->belongsToMany(EloquentRoleModelStub::class, 'role_user', 'user_id', 'role_id');
}

User::query()->joinRelation('roles as users_roles,roles');
// SQL: select * from "users" inner join "role_user" as "users_roles" on "users_roles"."user_id" = "users"."id" inner join "roles" on "roles"."id" = "users_roles"."role_id"

User::query()->joinRelation('roles as users_roles,positions');
// SQL: select * from "users" inner join "role_user" as "position_user" on "position_user"."user_id" = "users"."id" inner join "roles" as "positions" on "positions"."id" = "position_user"."role_id"

7. 其他一切

您需要用于连接的所有其他内容:聚合、分组、排序、选择等,都通过已建立的查询构建器进行,那里没有做任何改变。这意味着我可以轻松地做这样的事情

User::query()->joinRelation('licenses')->groupBy('users.id')->orderBy('users.id')->select('users.id')->selectRaw('sum(licenses.price) as revenue');

我个人认为,我会在 Laravel Nova(特别是透镜)中大量使用这个功能,但多年来,在无数场景中,我一直需要这样的查询。

连接是几乎每个开发者最终都会使用的东西,所以如果 Eloquent 本地支持通过关系进行连接将是极好的。然而,由于这并不是默认提供的,您将不得不安装这个包。我的目标是让这个包的编码感觉与 Laravel 相似,复杂实现(如通过命名关系进行连接)简单易用、易于理解。