stillat / relationships

提供双向条目关系自动化

资助包维护!
JohnathonKoster

安装次数: 23,550

依赖关系: 1

建议者: 0

安全: 0

星标: 18

关注者: 3

分支: 1

公开问题: 0

类型:statamic-addon

v2.2.1 2024-06-29 19:04 UTC

README

Entry Relationships 通过简单的方式自动同步相关 Statamic 条目。

概述

条目关系可以帮助显著简化相关条目之间的同步。

例如,如果您有一个包含 sponsored_by(包含赞助商列表)字段的 conferences 集合,需要与包含 sponsoring(包含赞助商赞助的会议列表)字段的 sponsors 集合保持同步,Entry Relationships 扩展程序允许您像这样表达这种关系:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::manyToMany(
            'conferences.sponsored_by',
            'sponsors.sponsoring'
        );
    }
}

创建关系后,Entry Relationships 将利用 Statamic 的条目事件来自动同步。

关系也是双向的。更新会议条目将自动将会议添加到任何相关赞助商。相反更新赞助商?没问题!任何相关赞助商所相关的会议也会更新!

Entry Relationships 将跟踪并自动应用以下类型的更新:

  • 新的条目关系:向会议添加了新的赞助商。会议也将添加到 sponsors 条目中。
  • 删除关系:从会议中删除了赞助商。会议也将从 sponsors 条目中删除。
  • 删除相关条目:删除了 conferences 条目。任何引用已删除 conferencessponsors 都将更新,并将该会议删除。

安装方法

您可以在 Statamic 控制面板的 工具 > 扩展程序 部分搜索此扩展程序,并点击 安装,或者从您的项目根目录运行以下命令:

composer require stillat/relationships

使用方法

介绍结束后?太棒了!Entry Relationships 支持多种关系类型,并提供了一些辅助命令。

关系类型

Entry Relationships 支持以下类型的关系:

  • 多对多:可能有多个赞助商支持任何数量的会议,每个赞助商也可以支持任何数量的会议。
  • 多对一:许多书籍可能由单个作者撰写。
  • 一对多:一位作者可能撰写了许多书籍。
  • 一对一:特定的职位只能由一名员工担任,而一名员工一次只能担任一个职位。

支持的数据实体

Entry Relationships 支持以下数据实体:

  • 条目:集合条目。
  • 用户:个人用户。
  • 术语:分类术语。

默认情况下,Entry Relationships 将假设关系是条目之间的,以保持向后兼容性。要创建用户与条目之间的关系,您需要使用关系评估时使用的数据类型前缀关系。

例如,要创建会议集合与那些管理这些会议的用户之间的关系,我们可以使用以下类似的方法:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::manyToMany(
            'user:managing_conferences',
            'conferences.managed_by'
        );
    }
}

注意,我们只需指定字段名来引用用户。

要创建术语关系,我们必须指定实体类型以及分类名称。

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::manyToMany(
            'term:topics.posts',
            'posts.topics'
        );
    }
}

创建多对多关系

示例:会议可以有许多赞助商。每个赞助商可以支持许多会议。

要创建多对多关系,您需要两个集合。每个集合应包含一个 entries 字段,引用另一个集合。这两个字段都需要允许关联多个条目。

例如,假设以下集合设置

一个包含 sponsored_by 字段的 conferences 集合,该字段引用 sponsors 集合

sections:
  main:
    display: Main
    fields:
      -
        handle: title
        field:
          type: text
          required: true
          validate:
            - required
      -
        handle: sponsored_by
        field:
          mode: default
          create: true
          collections:
            - sponsors
          display: Sponsors
          type: entries
          icon: entries
          listable: hidden
          instructions_position: above
          read_only: false
title: Conferences

以及一个引用 conferences 集合的 sponsors 集合

sections:
  main:
    display: Main
    fields:
      -
        handle: title
        field:
          type: text
          required: true
          validate:
            - required
      -
        handle: sponsoring
        field:
          mode: default
          create: true
          collections:
            - conferences
          display: Sponsoring
          type: entries
          icon: entries
          listable: hidden
          instructions_position: above
          read_only: false
title: Sponsors

您可以在网站的服务提供者中定义以下关系(app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::manyToMany(
            'conferences.sponsored_by',
            'sponsors.sponsoring'
        );
    }
}

manyToMany 方法将自动为您定义反向关系。您 不需要 从赞助商到会议定义多对多关系。

如果您需要创建多个多对多关系,您可以选择使用集合语法,这提供了一种定义多个关系的快捷方式。例如,要将多个集合关联到一个分类法,您可以使用以下方法

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::manyToMany(
            'term:categories.field_name',
            'entry:{collection1,collection2,collection3,collection4}.field_name'
        );
    }
}

上述示例将在 categories 分类法和 field_name 字段之间创建多对多关系,并且等同于以下操作

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::manyToMany(
            'term:categories.field_name',
            'entry:collection1.field_name'
        );
        
        Relate::manyToMany(
            'term:categories.field_name',
            'entry:collection2.field_name'
        );

        Relate::manyToMany(
            'term:categories.field_name',
            'entry:collection3.field_name'
        );

        Relate::manyToMany(
            'term:categories.field_name',
            'entry:collection4.field_name'
        );
    }
}

创建一对多关系

示例:许多书可以由一位作者撰写。每位作者可以撰写许多书。

要创建一对多关系,您需要两个集合。每个集合应包含一个 entries 字段,引用另一个集合。

对于此关系,可以关联到单个其他条目的集合(本例中的 books)应将其 entries 字段设置为 max_items: 1。可以关联到多个条目的集合(本例中的 authors)应将其 entries 字段设置为允许关联多个条目。

使用引用单个作者的 books 集合

sections:
  main:
    display: Main
    fields:
      -
        handle: title
        field:
          type: text
          required: true
          validate:
            - required
      -
        handle: content
        field:
          type: markdown
          localizable: true
      -
        handle: author
        field:
          max_items: 1
          mode: default
          create: true
          collections:
            - authors
          display: Author
          type: entries
          icon: entries
          listable: hidden
          instructions_position: above
          read_only: false
title: Books

以及引用多个书籍的 authors 集合

sections:
  main:
    display: Main
    fields:
      -
        handle: title
        field:
          type: text
          required: true
          validate:
            - required
      -
        handle: content
        field:
          type: markdown
          localizable: true
      -
        handle: books
        field:
          mode: default
          create: true
          collections:
            - books
          display: Books
          type: entries
          icon: entries
          listable: hidden
          instructions_position: above
          read_only: false
title: Authors

您可以在网站的服务提供者中定义以下关系(app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::oneToMany(
            'books.author',
            'authors.books'
        );
    }
}

oneToMany 方法将自动为您创建反向的 manyToOne 关系。您不需要从 authors.booksbooks.author 创建关系。

创建一对多关系

示例:一位作者可以写许多书。每本书都由一位作者撰写。

这种关系是一对多关系的逆关系。

使用与 创建一对多关系 部分相同的设置,可以定义如下多对一关系

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::manyToOne(
            'authors.books',
            'books.author'
        );
    }
}

当使用 manyToOne 方法时,您不需要从 books.authorauthors.books 定义一对多的反向关系。这会自动为您完成。

创建一对一关系

示例:一个职位可能由一个员工担任。一个员工一次只能有一个职位。

要创建一对多关系,您需要两个集合。每个集合应包含一个 entries 字段,引用另一个集合。每个字段必须包含 max_items: 1 配置属性。

假设有一个 employees 集合

sections:
  main:
    display: Main
    fields:
      -
        handle: title
        field:
          type: text
          required: true
          validate:
            - required
      -
        handle: position
        field:
          max_items: 1
          mode: default
          create: true
          collections:
            - positions
          display: Position
          type: entries
          icon: entries
          listable: hidden
          instructions_position: above
          read_only: false
title: Employees

以及一个 positions 集合

sections:
  main:
    display: Main
    fields:
      -
        handle: title
        field:
          type: text
          required: true
          validate:
            - required
      -
        handle: filled_by
        field:
          max_items: 1
          mode: default
          create: true
          collections:
            - employees
          display: 'Filled By'
          type: entries
          icon: entries
          listable: hidden
          instructions_position: above
          read_only: false
title: Positions

您可以在网站的服务提供者中定义以下关系(app/Providers/AppServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::oneToOne(
            'employees.position',
            'positions.filled_by'
        );
    }
}

您不需要定义从 positions.filled_byemployees.position 的反向关系。这会自动为您完成。

其他事项

每个关系都有一些属性,您可以使用它们来控制 Entry Relationships 如何处理它们。这些属性包括

  • withEvents:默认值为false。当为true时,每个更新条目还会触发自己的EntrySavingEntrySaved事件
  • allowDelete:默认值为true。当为true时,删除条目将从任何相关条目中移除该条目

可以在定义关系后通过调用它们对应的方法来调整这些属性

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::manyToMany(
            'conferences.sponsored_by', 
            'sponsors.sponsoring'
        )->allowDelete(false)->withEvents(true);
    }
}

此外,您可以手动定义自己的关系(但使用之前介绍的方法会更简单)

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Stillat\Relationships\Support\Facades\Relate;

class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Relate::collection('conferences')
                ->field('sponsored_by')
            ->isRelatedTo('sponsors')
            -   >through('sponsoring')
            ->manyToMany();
    }
}

手动定义关系时,不会自动创建自动反向关系。

控制台命令

Entry Relationships 插件提供了一些控制台命令,可以帮助简化实施和调试。

该插件提供了以下命令

  • php please relate:list:列出所有定义的关系及其详细信息
  • php please relate:fill:强制插件检查所有条目是否相互同步。如果不一致,则将更新它们。

relate:list 命令

运行php please relate:list将显示所有定义关系的表格

Relationship List Table

第一列显示每个关系的索引编号。它除了帮助关联自动创建的反向关系外没有其他意义。

  • 主集合:在关系中首先出现的集合(提供的第一个集合处理程序,或集合)
  • 相关集合:在定义关系时最后出现的集合(提供的第二个集合处理程序,或集合)
  • 主字段:用于关系的字段处理程序,在集合中定义
  • 相关字段:用于关系的字段处理程序,在相关集合中定义
  • 关系:对关系类型的友好描述
  • 带事件:表示条目是否静默保存
  • 允许删除:表示相关条目在其相关条目被删除时是否会更新
  • 是否自动反向:表示关系是否为您自动创建。如果是,则您定义的关系索引将出现在括号中。

您可以通过以下方式将返回的结果限制为单个集合

php please relate:list collection

relate:fill 命令

此命令可以用来强制 Entry Relationships 插件检查和更新所有相关条目。

此命令的一个常见用例是您已经有一个 books 集合并将它们与 author 关联。之后,您在 authors 集合中添加了 books 字段。运行此命令将为您同步 booksauthors 条目。

relate:fill 命令支持一些选项

您可以通过以下方式将操作限制为单个集合

php please relate:fill collection

许可证

Entry Relationships 是在 MIT 许可下发布的免费软件。