提供了一种面向对象的API,以SQL风格查询内存集合。
Requires
- php: >=8.1
- symfony/property-access: ^6.1
This package is auto-updated.
Last update: 2024-09-04 19:07:48 UTC
README
安装
composer require alexandre-daubois/poq 1.0.0-beta2
好了,准备开始!🎉
用法
以下是我们将要在以下示例中使用的数据集
$cities = [ new City('Lyon', [ new Person([ new Child('Hubert', age: 30), new Child('Aleksandr', age: 18), new Child('Alexandre', age: 26), new Child('Alex', age: 25), ], height: 181), new Person([ new Child('Fabien', age: 23), new Child('Nicolas', age: 8), ], height: 176), new Person([ new Child('Alexis', age: 33), new Child('Pierre', age: 5), ], height: 185) ], minimalAge: 21), new City('Paris', [ new Person([ new Child('Will', age: 33), new Child('Alix', age: 32), new Child('Alan', age: 45), ], height: 185) ], minimalAge: 45) ];
ObjectQuery对象
The ObjectQuery
对象允许您轻松地以轻松的方式获取集合中的深层信息。就像Doctrine的QueryBuilder
一样,有许多实用的方法用于方便地操作。
此外,您还可以逐步创建查询,并在需要时进行条件化。要创建一个简单的查询,只需调用ObjectQuery
的from
工厂方法,并将您的集合作为其源即可
use ObjectQuery\ObjectQuery; $query = ObjectQuery::from($this->cities, 'city');
从这里开始,您就可以操作您的集合并获取数据。首先,让我们看看如何过滤您的集合。请注意,city
参数是可选的,并为当前集合定义了一个别名。默认情况下,别名为_
。每个别名在查询中必须是唯一的,这意味着在处理深层集合时,您必须传递一个别名。定义别名允许您在查询的后续部分引用对象。有关详细信息,请参阅selectMany
操作说明。
修改器(过滤、排序、限制等)
修改器允许过滤结果、排序、限制等。
🔀 修改器可以以任何顺序提供给查询,因为它们仅在调用操作时应用。
Where
用法
where
,它接受一个回调作为参数。此回调必须返回一个布尔值。
use ObjectQuery\ObjectQuery; $query = (ObjectQuery::from($this->cities, 'city')) ->where( function(City $city) { return \str_contains($city->name, 'Lyon') || \in_array($city->name, ['Paris', 'Rouen']); } );
Order by
orderBy
,它将排序集合。如果集合只包含标量值,那么您只需传递一个顺序。如果您的集合包含对象,您必须同时传递顺序以及排序的字段。可用的顺序是:QueryOrder::Ascending
、QueryOrder::Descending
、QueryOrder::None
和QueryOrder::Shuffle
。
use ObjectQuery\ObjectQuery; use ObjectQuery\ObjectQueryOrder; $query = (ObjectQuery::from($this->cities)) ->orderBy(ObjectQueryOrder::Ascending, 'name');
Offset
offset
修改器会更改将从集合中检索的第一个元素的位置。这在进行分页时特别有用,与limit
修改器结合使用。偏移量必须是一个正整数,或null
以移除任何偏移量。
use ObjectQuery\ObjectQuery; $query = ObjectQuery::from($this->cities); // Skip the 2 first cities of the collection and fetch the rest $query->offset(2) ->select(); // Unset any offset, no data will be skipped $query->offset(null) ->select();
Limit
limit
修改器限制不同操作(如select
)将使用的结果数。限制必须是一个正整数,或null
以移除任何限制。
use ObjectQuery\ObjectQuery; $query = ObjectQuery::from($this->cities); // Only the first 2 results will be fetched by the `select` operation $query->limit(2) ->select(); // Unset any limitation, all matching results will be used in the `select` operations $query->limit(null) ->select();
操作
操作允许您以特定格式检索过滤后的数据。以下是可用的操作列表及其用法。
Select
这是最基本操作。它返回查询的过滤数据。您可以传递要检索的确切字段,以及多个字段。如果没有传递给select
任何参数,它将检索整个对象。在处理标量集合时,您必须不传递任何参数。
use ObjectQuery\ObjectQuery; $query = ObjectQuery::from($this->cities); // Retrieve the whole object $query->select(); // Retrieve one field $query->select('name'); // Retrieve multiple fields $query->select(['name', 'minimalAge']);
Select One
当查询集合时,如果我们事先知道只有一个结果会匹配,则使用select
并每次检索结果数组的第一元素可能是多余的。selectOne
正是为此而设计的。此操作的如下所示
- 如果找到单个结果,它将直接返回,而不会将其包含在一个包含一个元素的数组中。
- 如果没有找到结果,则
selectOne
操作返回null
。 - 如果找到多个结果,则抛出
NonUniqueResultException
异常。
use ObjectQuery\Exception\NonUniqueResultException; $query = (ObjectQuery::from($this->cities, 'city')) ->where(fn($city) => $city->name === 'Lyon'); try { $city = $query->selectOne(); // $city is an instance of City // You can also query a precise field $cityName = $query->selectOne('name'); // $cityName is a string } catch (NonUniqueResultException) { // ... }
Select Many
此操作允许您更深入地访问集合。假设您的集合中包含许多内部有集合的对象,您将使用此操作来检索和过滤集合。
注意,我们为城市定义了一个别名,这允许在最后的 where
调用中引用父城市。
use ObjectQuery\ObjectQuery; use ObjectQuery\ObjectQueryContextEnvironment; $query = (ObjectQuery::from($this->cities, 'city')) ->where(fn($city) => \in_array($city->name, ['Paris', 'Rouen'])) ->selectMany('persons', 'person') ->where(fn($person) => $person->height >= 180) ->selectMany('children', 'child') ->where(fn($child, ObjectQueryContextEnvironment $context) => \str_starts_with($child->name, 'Al') && $child->age >= $context->get('city')->minimalAge);
与 from
一样,selectMany
也接受一个别名作为参数。这样,您将能够在 where
调用中引用祖先,如上述示例所示。
计数
此操作返回当前过滤集合的大小
$query = ObjectQuery::from($this->cities); $query->count();
连接
此操作将使用给定的分隔符将集合连接起来。如果您处理的是标量集合,则没有强制参数。如果处理的是对象的集合,则必须传递 field
参数。
$query = ObjectQuery::from($this->cities); $query->concat(', ', 'name');
每个
此操作允许您传递一个回调,该回调将被应用于过滤集合的每个元素。您可以将此视为一个 foreach
。
$query = ObjectQuery::from($this->cities); // Append an exclamation point to every city name $query->each(fn($element) => $element->name.' !');
最小值和最大值
这些操作将返回集合的最大值和最小值。您可以使用此操作对标量集合进行操作。内部,这些操作使用标准 PHP 库中的 min()
和 max()
函数,因此适用相同的规则。
use ObjectQuery\ObjectQuery; $query = (ObjectQuery::from($this->cities)) ->selectMany('persons', 'person') ->selectMany('children', 'child'); $query->min('age'); // 5 $query->max('age'); // 45 $query->min('name'); // "Alan" $query->max('name'); // "Will"
求和
sum
返回集合的总和。如果集合包含对象,必须提供字段以计算其总和。此操作仅适用于数值集合,如果集合中的任何项对 \is_numeric()
函数返回 false
,则抛出异常。
use ObjectQuery\ObjectQuery; $query = (ObjectQuery::from($this->cities)) ->selectMany('persons', 'person') ->selectMany('children', 'child'); $query->sum('age');
平均值
average
返回集合的平均值。如果集合包含对象,必须提供字段以计算其平均值。此操作仅适用于数值集合,如果集合中的任何项对 \is_numeric()
函数返回 false
,则抛出异常。
use ObjectQuery\ObjectQuery; $query = (ObjectQuery::from($this->cities)) ->selectMany('persons', 'person') ->selectMany('children', 'child'); $query->average('age');