clickbar/laravel-custom-relations

此包为 Laravel 提供自定义关系的功能

1.0.1 2024-04-15 14:35 UTC

This package is auto-updated.

Last update: 2024-09-08 01:57:43 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Laravel 从一开始就提供了一些相当好的关系。如果这些关系不符合需求,社区也提供了很多其他的关系包。特别是 staudenmeir 在这方面做了很多优秀的工作。然而,在我们的项目中,我们遇到了一些需要真正自定义关系的需求,这些关系可以用优雅的查询轻松表达,但不能用默认关系表达。因此,我们创建了此包,以让您完全控制自己的关系。

简介

有时需要更多定制。此包扩展了默认的 Laravel 关系,使其可以通过查询来描述关系。

为了说明,我们考虑以下模型,其中有一个简单的连接关系用例。(对于此类用例,您还应该查看 staudenmeir 的 eloquent-has-many-deep)。即使示例相当简单,也应该能够代表自定义关系带来的巨大可能性。 model chain

让我们以默认 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 中所知道的,关系可以返回模型集合或单个模型。因此,此包有两个不同的关系 CustomRelationCustomRelationSingle

让我们看看上面的两个示例

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)。请参阅 许可文件 了解更多信息。