clickbar / laravel-custom-relations
此包为 Laravel 提供自定义关系的功能
Requires
- php: ^8.1
- illuminate/contracts: ^10.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- larastan/larastan: ^2.0.1
- laravel/pint: ^1.0
- nunomaduro/collision: ^7.8
- orchestra/testbench: ^8.8
- pestphp/pest: ^2.20
- pestphp/pest-plugin-arch: ^2.5
- pestphp/pest-plugin-laravel: ^2.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
README
Laravel 从一开始就提供了一些相当好的关系。如果这些关系不符合需求,社区也提供了很多其他的关系包。特别是 staudenmeir 在这方面做了很多优秀的工作。然而,在我们的项目中,我们遇到了一些需要真正自定义关系的需求,这些关系可以用优雅的查询轻松表达,但不能用默认关系表达。因此,我们创建了此包,以让您完全控制自己的关系。
简介
有时需要更多定制。此包扩展了默认的 Laravel 关系,使其可以通过查询来描述关系。
为了说明,我们考虑以下模型,其中有一个简单的连接关系用例。(对于此类用例,您还应该查看 staudenmeir 的 eloquent-has-many-deep)。即使示例相当简单,也应该能够代表自定义关系带来的巨大可能性。
让我们以默认 Laravel 的方式来探索 Client 和 Task 之间的连接
$client = $task->order->project->client; $tasks = $client->projects->flatMap(fn(Project $project) => $project->order->flatMap(fn(Order $order) => $order->tasks));
如果只使用一个数据库查询来做这样的事情,不是很好吗?
$client = $task->client; $tasks = $client->tasks;
使用自定义关系,您只需一个数据库查询即可完成此操作。
安装
您可以通过 composer 安装此包
composer require clickbar/laravel-custom-relations
准备模型
为了使用自定义关系,您必须使用 HasCustomRelation
特性
use Clickbar\LaravelCustomRelations\Traits\HasCustomRelation; class Client extends Model{ use HasCustomRelation; ... }
编写关系
正如您从 Laravel 中所知道的,关系可以返回模型集合或单个模型。因此,此包有两个不同的关系 CustomRelation
和 CustomRelationSingle
。
让我们看看上面的两个示例
class Task extends Model { use HasCustomRelation; public function client(): CustomRelationSingle { return $this->customRelationSingle( Client::class, function ($query) { $query ->join('projects', 'clients.id', 'client_id') ->join('orders', 'projects.id', 'project_id') ->join('tasks', 'orders.id', 'order_id'); }, ); } }
class Client extends Model { use HasCustomRelation; public function tasks(): CustomRelation { return $this->customRelation( Task::class, function ($query) { $query ->join('orders', 'orders.id', 'order_id') ->join('projects', 'projects.id', 'project_id') ->join('clients', 'clients.id', 'client_id'); }, ); } }
与常规 Laravel 关系一样,查询构建器从相关模型开始。这导致了以下连接链
$task->client: Client->Projects->Orders->Tasks
$client->tasks: Tasks->Orders->Projects->Client
如果您更喜欢从定义关系的模型开始连接,您可以使用带有 fromParent
后缀的方法
class Task extends Model { use HasCustomRelation; public function client(): CustomRelationSingle { return $this->customRelationFromParentSingle( Client::class, function ($query) { $query ->join('orders', 'orders.id', 'order_id') ->join('projects', 'projects.id', 'project_id') ->join('clients', 'clients.id', 'client_id'); }, ); } }
class Client extends Model { use HasCustomRelation; public function tasks(): CustomRelation { return $this->customRelationFromParent( Task::class, function ($query) { $query ->join('projects', 'clients.id', 'client_id') ->join('orders', 'projects.id', 'project_id') ->join('tasks', 'orders.id', 'order_id'); }, ); } }
限制
由于查询可能会引入许多连接,因此 Laravel 关系中的一些方法不可用
- make
- create
- update
- forceCreate
- forceDelete
测试
composer test
更改日志
请参阅 CHANGELOG 了解最近更改的详细信息。
贡献
请参阅 CONTRIBUTING 了解详细信息。
安全漏洞
请参阅 我们的安全策略 了解如何报告安全漏洞。
鸣谢
许可
MIT 许可证 (MIT)。请参阅 许可文件 了解更多信息。