drderpling/eloquent-directus-repository

此软件包最新版本(v0.3.0-alpha)没有可用的许可证信息。

一个Laravel软件包,将Directus用作Eloquent模型的存储库。

v0.3.0-alpha 2024-05-20 18:38 UTC

This package is auto-updated.

Last update: 2024-09-20 21:36:44 UTC


README

此软件包实现了仓库模式,允许在Laravel应用程序中将数据从Directus懒加载到Eloquent模型中。

要求

  • PHP 8.1或更高版本
  • Laravel 11或更高版本
  • Directus 10或更高版本
  • 模型必须正确配置$fillable属性,以确保安全地处理批量赋值。

安装

composer require drderpling/eloquent-directus-repository

用法

创建新存储库

要创建新存储库,在一个新类中扩展EloquentDirectusRepository并实现getContext()方法以返回一个配置好的Context对象。此对象指定要加载的模型和字段。

基本存储库设置的示例

use DrDerpling\DirectusRepository\EloquentDirectusRepository;

class MyRepository extends EloquentDirectusRepository {
    public function getContext(): Context {
        return ContextFactory::create(MyModel::class);
    }
}

上下文对象

为了使存储库知道要加载哪个模型,我们需要提供一个上下文。上下文是一个对象,它定义了应该加载的模型。此对象使用ContextFactory::create()方法创建。此方法将模型类作为参数。

use DrDerpling\DirectusRepository\Context\ContextFactory;
use DrDerpling\DirectusRepository\Context\Context;

class MyRepository extends EloquentDirectusRepository
{
      public function getContext(): Context
    {
        return ContextFactory::create(MyModel::class);
    }
}

选项

ContextFactory::create()方法有4个参数。以下将分别说明每个参数。

ContextFactory::create()选项

$fillable属性添加到模型

为了使存储库能够将数据保存到数据库,模型必须有一个$fillable属性。此属性应是一个允许批量赋值的字段数组。这是一个安全功能,用于防止不希望的字段被保存到数据库中。

class MyModel extends Model
{
    protected $fillable = [
        'name',
        'description',
    ];
}

有关$fillable属性的更多信息,请参阅Laravel文档:https://laravel.net.cn/docs/11.x/eloquent#mass-assignment

方法

getList()

要获取记录列表,可以调用getList()方法。这将返回一个记录集合。类似于eloquent中的all()方法。

$repository = new MyRepository();

$records = $repository->getList();

get()

要获取单个记录,可以调用带有要加载的记录id的get()方法。这将返回一个记录。此id是您自己的数据库id,而不是directus id。有关通过directus id加载的信息,请参阅get getByCmsId

$repository = new MyRepository();

$record = $repository->get(1);

getByCmsId()

要获取通过directus id的单个记录,可以调用带有要加载的记录id的getByCmsId()方法。这将返回一个记录。提供的id是directus的id,而不是您自己的数据库id。有关更多信息,请参阅get id。

$repository = new MyRepository();

$record = $repository->getByCmsId(1);

高级用法

在某些情况下,您可能需要从多个集合中加载数据或在对数据保存到数据库之前对其进行一些预处理。本节解释了如何通过覆盖您的存储库中的特定方法来自定义数据处理过程。

准备数据

在数据保存到数据库之前,会调用prepareData()方法。此方法提供了操纵数据数组的机会,并应返回一个包含准备好的数据的Laravel Collection

例如,当加载带有相关SkillsProject模型时,您可能需要处理技能并将它们追加到主数据数组中

public function getContext(): Context {
    return ContextFactory::create(Project::class, [
        'id',
        'hero',
        'name',
        'image',
        'status',
        'description',
        'short_description',
        'content',
        'url',
        'skills.*',
    ]);
}

protected function prepareData(array $data): Collection {
    $item = collect($data);
    $item->put('cms_id', $item->get('id'));

    $skills = array_map(static function ($skill) {
        return [
            'id' => $skill['skills_id'],
            'sort' => $skill['sort'],
        ];
    }, $item->get('skills'));

    $item->put('skills', $skills);
    return $item;
}

在上面的示例中,skills数据被处理和结构化,以便与Project模型兼容,然后再保存。

模型创建或更新

updateOrCreate() 方法用于根据提供的数据创建或更新模型实例。此方法可以被覆盖以包含处理复杂关系或额外字段(这些字段不是模型主要部分)的自定义逻辑。

以下是处理复杂数据关系的方法,例如将技能附加到项目上

public function updateOrCreate(Collection $item): Model {
    /** @var Project $project */
    $project = $this->getContext()->getModelClass()::updateOrCreate(
        ['cms_id' => $item->get('cms_id')],
        $item->toArray()
    );

    // Assuming 'skills' data is provided as an array of skill IDs and sort values
    $skillCmsIds = array_map(static fn($skill) => $skill['id'], $item->get('skills'));
    $skillIds = $this->skillRepository->getSkillIds($skillCmsIds);

    $project->skills()->detach(); // Detach existing skills to avoid duplicates
    foreach ($item->get('skills') as $skill) {
        $project->skills()->attach($skillIds[$skill['id']], ['sort' => $skill['sort']]);
    }

    return $project;
}

在这个示例中,更新或创建 Project 模型后,相关的 Skills 通过使用 Laravel Eloquent 关系的 attach 方法进行处理和附加。这确保了项目技能与 Directus 的更改同步更新。

这些高级方法为您在存储库中提供灵活性和健壮性,允许进行现实世界应用中常见的复杂数据交互。