提供了一种面向对象的API,以SQL风格查询内存集合。

1.0.0-beta2 2022-07-04 13:59 UTC

This package is auto-updated.

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


README

Minimum PHP Version CI Latest Unstable Version License

安装

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一样,有许多实用的方法用于方便地操作。

此外,您还可以逐步创建查询,并在需要时进行条件化。要创建一个简单的查询,只需调用ObjectQueryfrom工厂方法,并将您的集合作为其源即可

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::AscendingQueryOrder::DescendingQueryOrder::NoneQueryOrder::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');