tkeer/flattable

将多个表合并为一个扁平的超级表。

v4.0 2024-07-04 18:58 UTC

This package is auto-updated.

Last update: 2024-09-04 19:18:07 UTC


README

laravel flattable

Laravel Flattable Build Status Build Status Build Status

它允许您通过简单的配置来管理非规范化表。

只需在模型中添加基于数组的配置,它将自动同步您的非规范化表。

简介

您当前在Laravel应用程序中是否有非规范化表,或者计划添加一个,这个包可以帮助您保持非规范化表与源表同步。

使用flattable,您可以将多个表合并为一个大型表,并通过以下方式提高性能:

最小化连接和子查询的需求,预先计算聚合值,即在数据修改时计算,而不是在选择时计算

laravel flattable

您只需要创建一个扁平表,在相关模型中添加配置,然后一切都将自动开始工作。

安装

使用Composer安装此包

composer require tkeer/flattable

Laravel版本兼容性

用法

  1. Flattable特质添加到您的模型中
  2. 实现flattableConfig方法并添加您的配置

通过示例学习

通过示例更容易解释。有关更详细的示例,请参阅测试

示例数据库结构

  1. 我们有书籍、出版商、国家表
  2. 一本书属于一个出版商
  3. 一个出版商属于一个国家

我们想在书的扁平表(books_flattable)中获取书籍、书籍的出版商和书籍出版商的国家数据

laravel flattable

由于书是这里的主要表,我们将在书的模型中添加扁平配置,并将type设置为primary,更多关于类型请在此

为了解释这个问题,我们将把我们的配置分为三个部分。有关书籍的详细配置,请参阅测试中book模型的第一个配置条目。

1. 书籍在书的扁平表中

当相关书籍更新或删除时,也会更新/删除

Book模型的getFlattableConfig()方法中

public function getFlattableConfig(): array
{
  [
    [

      'columns' => [

        //flattable column => 'source model column'
        'name' => 'name',
        'published_at' => 'published_at',
        'publisher_id' => 'publisher_id',
        'book_id' => 'id'

      ],

      // type of relationship b/w flattable and model
      'type' => 'primary',

      // how to find related entry in the flattable table
      'wheres' => [

        // key is flattable column
        // value is column of source table (book)
        'book_id' => 'id',

      ],

      'flattable' => 'books_flattable',
    ]
  ]
}

2. 书的扁平表中的出版商

当书的出版商更改时,也会更新扁平表中的新出版商

扩展上面的扁平配置,并在changes键下添加出版商的配置。

public function getFlattableConfig(): array
{
  [

    [

      'flattable' => 'books_flattable',
      ...

      'changes' => [

        // foreign colum name
        // we will update changes data only if this column is update(dirty)

        'publisher_id' => [

          'columns' => [

            'publisher_first_name' => 'first_name',
            'publisher_last_name' => 'last_name',

          ],   

          // talbe name of the source
          'table' => 'publishers',
        ]
      ]
    ]
  ]
}

3. 出版商的国家在书的扁平表中

[
    //inside pubilsher config of books flattable
    ...
    'changes' => [
        'country_id' => [
            'columns' => [
                'publisher_country_name' => 'name',
                'publisher_country_id' => 'id',
            ],
            'where' => [
                'id' => 'country_id'
            ],
            'table' => 'countries'
        ]
    ]
]

您可以使用changes属性进行多层嵌套,即changes属性中的changes属性。

截至目前,添加了配置,书籍的任何更改都将自动更新书籍的扁平化。即使书籍的出版商发生变化,扁平化也会自动更新为新的出版商数据。

如果出版商本身也进行了更新,例如出版商的first_name更新了,或者出版商的国家更新了。为此,我们必须为PublisherCountry模型实现扁平化,并在两个模型中添加扁平化配置,配置type应为secondary

见下文

在出版商更新时更新书籍的扁平化

Publisher模型的flattableConfig()

public function flattableConfig()
{
  return [
    [
      'columns' => [
          'publisher_first_name' => 'first_name',
          'publisher_last_name' => 'last_name',
      ],
      'wheres' => [
          'publisher_id' => 'id',
      ],
      'type' => 'secondary',

      'flattable' => 'books_flattable',
    ]
  ]
}

在国家更新时更新书籍的扁平化

当删除国家时,为扁平化分配null值

Country模型的flattableConfig()

public function flattableConfig()
{
  return [
    [
      'columns' => [
          'publisher_country_name' => 'name',
          'publisher_country_id' => 'id',
      ],
      'wheres' => [
          'publisher_country_id' => 'id',
      ],
      'type' => 'secondary',

      'flattable' => 'books_flattable',
    ]
  ]
}

出版商的扁平表中的书籍

到目前为止,我们已经考虑了一对一的关系,书籍属于一个出版商,出版商属于一个国家。

如果两个表之间存在一对一的关系怎么办。

例如,出版商可以拥有许多书籍,并且每当添加任何书籍时,我们希望在出版商的扁平化中添加这本书。

Book模型中添加一个额外的扁平化配置,此关系的配置type应为many

public function flattableConfig(): array
{
  ...
  return [
            [
            'columns' => [
                'id' => 'id',
                'name' => 'name'
            ],

            // use type many when you want to store more than one entry in a column
            'type' => 'many',

            'wheres' => [
                'publisher_id' => 'publisher_id',
            ],
            //only delete from old if these keys have changed
            'delete_from_old_keys' => ['publisher_id'],

            'flattable' => 'publishers_flattable',

            // column name of the flaatable, in which the data should be stored.
            'flattable_column_name' => 'books',
        ]
  ]
}

扁平化配置说明

扁平化配置有以下属性

1. 列

2. 条件

3. 扁平化

4. 变更

5. 类型

6. 扁平化列名称

7. 从旧键中删除

8. 删除主键

1. 列

一个数组,包含扁平化列和源表列的映射。

columns数组中的每个键都是扁平化列的名称,其值是源表列的名称。

[
  'columns' => [
    'book_id' => 'id',
    'book_name' => 'name'
  ]
]

2. 条件

一个关联数组,包含映射扁平化中相关条目的条件。

子数组中的键是扁平化列的列名,其值是源表列的列名。

[
  'wheres' => [
    'book_id' => 'id'
  ]
]

3. 扁平化

扁平化的名称。

4. 变更

将相关表的数据包含到扁平化中。它应该是一个关联数组。

changes属性中每个数组的键是源表列的列名,其变化将加载扁平化中的相关数据。

5. 类型

它描述了扁平化和源表之间的关系类型

我们有三种类型

1. 主

创建、更新和删除对扁平化执行相同操作。

例如,书籍与books_flattable的关系

2. 次要

与主相同,但删除模型不会删除扁平化中的相关条目。相反,它将在扁平化中相关列中分配null值。

例如,出版商与books_flattable的关系。如果删除书籍的出版商,则books_flattable中的出版商属性将被设置为null。

如果您想要在扁平化中删除次要类型的条目,将deletes_primary标志设置为true

3. 多

对于一对一关系。使用此类型,我们可以在扁平化中存储多个条目。

例如,书籍与publishers_flattable的关系,一个出版商可以有多本书籍。

6. 扁平化列名称

当类型为many时是必需的。它持有扁平化的列名,其中将存储json数据。

7. 从旧键中删除

当类型为many时是必需的。它持有列的名称,任何这些列的变化都将重新加载相关扁平化列的相关json数据。

8. 删除主键

type自动从扁平化中删除条目,当主表中删除条目时,而次要类型将null值存储在扁平化中的相关条目中。

如果您想要删除次要类型的条目也删除相关的扁平化条目,将deletes_primary标志设置为true。

配置

禁用单个模型的扁平化

Book::disableFlattable();

$book = factory(Book::class)->create();
$bookFlattable = BookFlattable::where('book_id', $book->id)->first();
$this->assertNull($bookFlattable);

Book::enableFlattable();

禁用所有模型的扁平化

发布扁平化配置

php artisan vendor:publish --provider="Tkeer\Flattable\FlattableServiceProvider" --tag="config"

config/flattabe.php中将disabled设置为true

return [
    'console' => [
        'run' => true
    ],
    'disabled' => true
];

禁用控制台中的可展开功能

当脚本通过控制台运行时,您可以选择性地禁用可展开功能。

要禁用,请在 config/flattable.php 中将 console.run 设置为 false

使用回调

如果现有选项都不适用于您的用例,您可以传递回调函数给 columnswheres 配置。

对于 columns 回调,您将接收到模型作为参数,您应该返回一个数组,该数组将被存储在可展开中。

[
  ...

  'columns' => function (Country $country) {
    // when secondary row is deleted, it's data should be removed from flattable
    return [
      'publisher_country_name' => $country->exists ? $country->name ? null,
      'publisher_country_id' => $country->exists ? $country->id ? null
    ];
  }

  ...
]

对于 wheres 回调,您将接收到 QueryBuilderModel 作为参数,您可以添加任意多的条件。

[
  ...
  'wheres' => function (Builder $db, Country $model) {
    $db->where('publisher_country_id', $model->id);
  }

  ...
]

填充可展开

您可以使用 flattable:fill 命令来填充您的可展开。

php artisan flattable:fill App\\Models\\Book

此命令将使用 Book 模型的默认配置来填充相关的可展开。