yiisoft/data

数据提供者、分页和相关抽象

1.0.1 2023-01-25 17:12 UTC

This package is auto-updated.

Last update: 2024-09-10 17:51:04 UTC


README

Yii

Yii 数据


Latest Stable Version Total Downloads Build status Code Coverage Mutation testing badge static analysis type-coverage psalm-level

该包提供通用数据抽象。目标是隐藏读取、写入和处理数据操作中的存储方面。

特性包括

  • 具有计数、排序、限制和偏移、读取条件筛选器和后筛选的数据读取抽象。
  • 包含偏移和键集实现的分页抽象。
  • 数据写入抽象。
  • 数据处理抽象。

要求

  • PHP 8.1 或更高版本。

安装

该包可以通过Composer安装

composer require yiisoft/data

通用用法

概念

  • 每个数据集由项目组成。
  • 每个项目有多个命名字段。
  • 数据集中的所有项目都具有相同的结构。

读取数据

数据读取器的目标是读取数据库、数组或API等存储中的数据,并将其转换为简单的字段 => 值迭代器。

$reader = new MyDataReader(...);
$result = $reader->read(); 

结果是 iterable,因此您可以对其使用 foreach。如果您需要一个数组,可以通过以下方式实现

// using is foreach
foreach ($result as $item) {
    // ...
}

// preparing array
$dataArray = $result instanceof \Traversable ? iterator_to_array($result, true) : (array)$result;

限制读取的项目数量

您可以在迭代器中限制项目数量

$reader = (new MyDataReader(...))->withLimit(10);
foreach ($reader->read() as $item) {
    // ...
}

计数总项目数量

要了解实现 CountableDataInterface 的数据读取器中的项目总数

$reader = new MyDataReader(...);
$total = count($reader);

筛选

数据筛选可以分两步完成

  1. 形成获取数据的条件。这通过“筛选”完成。
  2. 通过迭代和检查每个项目进行数据后筛选。这通过带有筛选器的 IterableDataReader 完成。

尽可能使用条件,因为它通常能提供更好的性能。

要在实现 FilterableDataInterface 的数据读取器中筛选数据,您需要向 withFilter() 方法提供筛选器

$filter = new All(
    new GreaterThan('id', 3),
    new Like('name', 'agent')
);

$reader = (new MyDataReader(...))
    ->withFilter($filter);

$data = $reader->read();

筛选器可以组合使用

  • 所有
  • 任意
  • 介于
  • 等于
  • 等于空
  • 大于
  • 大于等于
  • 不区分大小写地等于
  • 在...之中
  • 小于
  • 小于等于
  • 类似

使用数组筛选

所有任意 筛选器有 withCriteriaArray() 方法,允许您使用数组定义筛选器。

$dataReader->withFilter((new All())->withCriteriaArray([
    ['=', 'id', 88],
    [
       'or',
       [
          ['=', 'color', 'red'],
          ['=', 'state', 1],
       ]
    ]
]));

实现自己的筛选器

要拥有自己的筛选器

  • 至少实现 FilterInterface,它包括
    • getOperator() 方法,它返回表示筛选操作的字符串。
    • toArray() 方法,它返回一个包含筛选参数的数组。
  • 如果您想为特定的数据读取器类型创建筛选器处理程序,那么您需要至少实现 FilterHandlerInterface。它有一个单一的 getOperator() 方法,该方法返回表示筛选操作的字符串。此外,每个数据读取器都指定了一个扩展接口,用于处理或构建操作。例如,IterableDataFilter 定义了 IterableFilterHandlerInterface,它包含额外的 match() 方法来在 PHP 变量上执行筛选操作。

您可以使用withFilterHandlers()方法向数据读取器添加自己的过滤器处理程序。您可以向读取器添加任何过滤器处理程序。如果读取器无法使用过滤器,则过滤器会被忽略。

// own filter for filtering
class OwnNotTwoFilter implenents FilterInterface
{
    private $field;

    public function __construct($field)
    {
        $this->field = $field;
    }
    public static function getOperator(): string
    {
        return 'my!2';
    }
    public function toArray(): array
    {
        return [static::getOperator(), $this->field];
    }
}

// own iterable filter handler for matching
class OwnIterableNotTwoFilterHandler implements IterableFilterHandlerInterface
{
    public function getOperator(): string
    {
        return OwnNotTwoFilter::getOperator();
    }

    public function match(array $item, array $arguments, array $filterHandlers): bool
    {
        [$field] = $arguments;
        return $item[$field] != 2;
    }
}

// and using it on a data reader
$filter = new All(
    new LessThan('id', 8),
    new OwnNotTwoFilter('id'),
);

$reader = (new MyDataReader(...))
    ->withFilter($filter)
    ->withFilterHandlers(
        new OwnIterableNotTwoFilter()
        new OwnSqlNotTwoFilter()    // for SQL
        // and for any supported readers...
    );

$data = $reader->read();

排序

要在实现SortableDataInterface的数据读取器中对数据进行排序,您需要向withSort()方法提供一个排序对象。

$sorting = Sort::only([
    'id',
    'name'
]);

$sorting = $sorting->withOrder(['name' => 'asc']);
// or $sorting = $sorting->withOrderString('name');

$reader = (new MyDataReader(...))
    ->withSort($sorting);

$data = $reader->read();

Sort的目标是将逻辑字段排序映射到实际数据集字段排序,并形成数据读取器的标准。逻辑字段是用户操作的字段。实际字段是数据集中实际存在的字段。这种映射有助于您需要根据单个逻辑字段进行排序时,该逻辑字段实际上由数据集中多个字段组成的情况。例如,您提供了一个包含实际数据集中姓氏和名字字段的用户名。

要获取Sort实例,您可以使用Sort::only()Sort::any()。使用Sort::only()会忽略没有配置的逻辑字段的用户指定顺序。Sort::any()将直接使用用户指定的逻辑字段名和顺序用于没有配置的字段。

无论如何,您都需要传递一个配置数组,该数组指定哪些逻辑字段应该是可排序的,以及这些字段如何映射到实际字段顺序的详细信息。

要应用的当前顺序通过withOrder()指定,您提供一个与逻辑字段名对应的键和顺序(ascdesc)对应的值的数组。或者可以使用withOrderString()。在这种情况下,排序顺序表示为包含逗号分隔的逻辑字段名的单个字符串。如果名称前缀为-,则排序方向设置为desc

跳过一些项

如果您需要跳过实现OffsetableDataInterface的数据读取器开头的一些项,请执行以下操作。

$reader = (new MyDataReader(...))->withOffset(10);

实现自己的数据读取器

要拥有自己的数据读取器,您至少需要实现DataReaderInteface。它有一个read()方法,该方法返回表示一组项的可迭代对象。

可以实现其他接口以支持不同的分页类型、排序和过滤。

  • CountableDataInterface - 允许获取数据读取器中的项目总数。
  • FilterableDataInterface - 允许根据标准返回项的子集。
  • LimitableDataInterface - 允许返回项的有限子集。
  • SortableDataInterface - 允许根据一个或多个字段进行排序。
  • OffsetableDataInterface - 允许在读取数据时跳过前N个项。

请注意,在实现这些方法时,不应修改数据,而应仅定义在后续的read()中使用以影响返回哪些数据的准则。

分页

分页允许获取有限的数据子集,这对于按页显示项以及在大数据集上获取可接受的性能都很有用。

提供了两种分页类型:传统偏移分页和键集分页。

偏移分页

偏移分页是一种常见的分页方法,它选择OFFSET + LIMIT项,然后跳过OFFSET项。

优点

  • 可以获取总页数
  • 可以访问特定页面
  • 数据可以无序
  • 考虑数据读取器中设置的限制

缺点

  • 随着页面数的增加,性能会降低
  • 数据中间的插入或删除会使结果不一致

用法如下

$reader = (new MyDataReader(...));

$paginator = (new OffsetPaginator($dataReader))
            ->withPageSize(10)
            ->withCurrentPage(2);


$total = $paginator->getTotalPages();
$data = $paginator->read();

键集分页

键集分页是一种替代的分页方法,适用于无限滚动和“加载更多”。它选择LIMIT项,这些项的关键字段值大于或小于(根据排序而定)指定的值。

优点

  • 性能不依赖于页面数
  • 无论插入和删除如何,结果都一致

缺点

  • 无法获取总页数
  • 无法访问特定页面,只有“上一页”和“下一页”
  • 数据不能是无序的
  • 数据读取器中设置的限制导致异常

用法如下

$sort = Sort::only(['id', 'name'])->withOrderString('id');

$dataReader = (new MyDataReader(...))
    ->withSort($sort);

$paginator = (new KeysetPaginator($dataReader))
    ->withPageSize(10)
    ->withToken(PageToken::next('13'));

当使用withNextPageToken()获取下一页时,使用最后显示的项目的第一页ID(或用于分页的其他字段名)

写入数据

$writer = new MyDataWriter(...);
$writer->write($arrayOfItems);

处理数据

$processor = new MyDataProcessor(...);
$processor->process($arrayOfItems);

文档

  • 指南:[葡萄牙语 - 巴西](https://github.com/yiisoft/data/blob/HEAD/docs/guide/pt-BR/README.md "Português - Brasil")
  • 内部

如果您需要帮助或有问题,[Yii 论坛](https://forum.yiiframework.com/c/yii-3-0/63 "Yii Forum")是一个不错的选择。您还可以查看其他[Yii 社区资源](https://yiiframework.cn/community "Yii Community Resources")。

许可

Yii 数据是免费软件。它在BSD许可协议下发布。有关更多信息,请参阅LICENSE

Yii 软件维护。

支持项目

Open Collective

关注更新

Official website Twitter Telegram Facebook Slack