yiisoft / data
数据提供者、分页和相关抽象
Requires
- php: ^8.0
- yiisoft/arrays: ^3.0
Requires (Dev)
- maglnet/composer-require-checker: ^4.2
- phpunit/phpunit: ^9.5
- rector/rector: ^0.15.0
- roave/infection-static-analysis-plugin: ^1.25
- spatie/phpunit-watcher: ^1.23
- vimeo/psalm: ^4.26|^5.4
This package is auto-updated.
Last update: 2024-09-10 17:51:04 UTC
README
Yii 数据
该包提供通用数据抽象。目标是隐藏读取、写入和处理数据操作中的存储方面。
特性包括
- 具有计数、排序、限制和偏移、读取条件筛选器和后筛选的数据读取抽象。
- 包含偏移和键集实现的分页抽象。
- 数据写入抽象。
- 数据处理抽象。
要求
- 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);
筛选
数据筛选可以分两步完成
- 形成获取数据的条件。这通过“筛选”完成。
- 通过迭代和检查每个项目进行数据后筛选。这通过带有筛选器的
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()
指定,您提供一个与逻辑字段名对应的键和顺序(asc
或desc
)对应的值的数组。或者可以使用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 软件维护。