icanboogie / facets

简化了实现分面搜索。

v0.8.0 2021-06-01 20:35 UTC

This package is auto-updated.

Last update: 2024-09-11 00:03:16 UTC


README

Release Build Status Code Quality Code Coverage Packagist

icanboogie/activerecord 包一起,此库简化了实现分面搜索。库使得解析查询字符串(单词袋)、使用序列化标准值(如集合(例如“1|2|3”)或区间(例如“1990..2010”)变得特别容易,并可以检索满足条件数组记录。

检索满足条件的记录

可以使用一个 BasicFetcher 实例来检索满足一系列条件的记录。该 fetcher 负责构建查询和检索匹配记录所需的各个步骤。这些步骤可以总结如下

  1. 解析指定的修饰符并提取条件、偏移量、限制、排序和查询字符串。
  2. 构建初始查询。
  3. 调用标准来修改查询。
  4. 使用条件修改查询。
  5. 计算与查询匹配的记录总数。
  6. 使用排序修改查询。
  7. 使用偏移量和限制修改查询。
  8. 检索与查询匹配的记录。
  9. 调用标准来修改记录。
  10. 返回一个包含记录的 RecordCollection 实例。

以下示例演示了如何使用 BasicFetcher 实例检索被归类在“音乐”类别中,且在2010年至2014年间发布的在线文章。最多可以检索10篇文章,并且它们按最近发布的顺序排列。

<?php

use ICanBoogie\ActiveRecord;
use ICanBoogie\Facets\Fetcher\BasicFetcher;

$model = ActiveRecord\get_model('articles');

$fetcher = new BasicFetcher($model);
$records = $fetcher([

    'year' => "2010..2014",
    'is_online' => true,
    'category' => "music",
    'order' => "-date",
    'limit' => 10

]);

使用模型检索记录

此包向 Model 实例添加了 fetch_records()fetch_record() 方法,允许直接从模型中检索记录,而无需构建 BasicFetcher 实例。

$records = $model->fetch_records([

    'year' => "2010..2014",
    'is_online' => true,
    'category' => "music",
    'order' => "-date",
    'limit' => 10

]);

请注意,可以使用方法的第二个参数获取用于检索记录的 BasicFetcher 实例。

$records = $model->fetch_records($conditions, $fetcher);

感兴趣的属性

记录返回后,以下属性可能值得关注

  • query_string:从 q 修饰符解析的 QueryString 实例。
  • conditions:用于过滤检索记录的条件数组。
  • order:检索记录的顺序,由 order 修饰符定义。
  • count:在应用偏移量和限制之前与查询匹配的记录数。

修改检索的记录

检索到的记录以 RecordCollection 实例的形式返回,此类实例可以用来触发类 RecordCollection\AlterEventalter 事件。事件钩子可以使用此事件来修改集合中的记录,例如,使用单个查询检索与一系列文章相关联的图像。

<?php

use ICanBoogie\Facets\RecordCollection;

$records = $fetcher(…);

new RecordCollection\AlterEvent($records);

使用 CriterionList 实例检索记录

如果您觉得使用 BasicFetcher 实例不足以构成挑战,您可以使用 CriterionList 并自行完成所有艰巨的工作。

<?php

use ICanBoogie\Facets\CriterionList;
use App\Modules\Vehicles;

$criterion_list = new CriterionList([

    'family'   => Vehicles\Families\FamilyCriterion::class,
    'brand'    => Vehicles\Brands\BrandCriterion::class,
    'category' => Vehicles\Categories\CategoryCriterion::class,
    'color'    => Vehicles\Colors\ColorCriterion::class,
    'energy'   => Vehicles\Energies\EnergyCriterion::class,
    'engine'   => Vehicles\Engines\EngineCriterion::class,
    'doors'    => Vehicles\DoorsCriterion::class,
    'year'     => Vehicles\YearCriterion::class,
    'price'    => Vehicles\PriceCriterion::class

]);

$modifiers = $_GET + [

    'q' => null,     // reserved keyword for query string
    'order' => null  // reserved keyword for records order

];

if ($modifiers['q'])
{
    $q = $criterion_list->parse_query_string($modifiers['q']);

    echo "The following words were matched: " . implode(' ', $q->matched) . '<br />';
    echo "The following words were not matched: " . implode(' ', $q->not_matched) . '<br />';

    // we choose to _OR_ criterion values
    $modifiers += array_map(function($v) { return implode('|', $v); }, $q->matches);
}

#
# Parameters are passed by reference, $values and $query are likely to be modified.
#

$conditions = [];

$criterion_list
->alter_conditions($conditions, $modifiers)
->alter_query($query)
->alter_query_with_conditions($query, $conditions);

if ($modifiers['order'])
{
    $criterion_list->alter_query_with_order($query, $modifiers['order']);
}

$count = $query->count;            // count all the records matching the query
$records = $query->limit(20)->all; // fetch a maximum of 20 records

准则值

准则值通常在 CriterionList 实例使用值修改查询时创建。如果值的键与准则标识符匹配,则调用该准则的 parse_value() 来检索一个 准则值,这可能是一个确切的值,也可能是如果值是复杂的情况下,例如 区间集合,则可能是一个 CriterionValue 实例。

产生的 准则值 用于在 alter_query_with_value() 期间修改查询。区间值 导致 BETWEEN ? AND ?=> ?<= ? 条件;而 集合值 导致 IN(?) 条件。

区间值

区间值由 IntervalCriterionValue 实例表示。当指定为字符串时,使用两个点 .. 来分隔下界和上界。可以使用以下任何语句创建区间值:

<?php

use ICanBoogie\Facets\CriterionValue\IntervalCriterionValue;

$value = IntervalCriterionValue::from('123..456'); // between 123 and 456
$value = IntervalCriterionValue::from('123..');    // >= 123
$value = IntervalCriterionValue::from('..456');    // <= 456

$value = IntervalCriterionValue::from([ 'min' => '123', 'max' => '456' ]); // between 123 and 456
$value = IntervalCriterionValue::from([ 'min' => '123', 'max' => null ]);  // >= 123
$value = IntervalCriterionValue::from([ 'min' => null, 'max' => '456' ]);  // <= 456

$value = new IntervalCriterionValue(123, 456);  // between 123 and 456
$value = new IntervalCriterionValue(null, 456); // >= 123
$value = new IntervalCriterionValue(123, null); // <= 456

IntervalCriterionValue 实例也可以用作字符串。

<?php

use ICanBoogie\Facets\CriterionValue\IntervalCriterionValue;

echo new IntervalCriterionValue(123, 456);    // "123..456"
echo new IntervalCriterionValue(123, null);   // "123.."
echo new IntervalCriterionValue(null, 456);   // "..456"
echo new IntervalCriterionValue(123, 123);    // "123"
echo new IntervalCriterionValue(null, null);  // ""

IntervalCriterionValue 实例可以在修改查询时由准则用来创建 BETWEEN ? AND ?>= ?<= ? 条件。

集合值

集合值由 SetCriterionValue 实例表示。当指定为字符串时,使用 竖线 符号 "|" 来分隔值。可以使用以下任何语句创建集合值:

<?php

use ICanBoogie\Facets\CriterionValue\SetCriterionValue;

$value = SetCriterionValue::from('1|2');                    // 1 or 2
$value = SetCriterionValue::from([ 1 => 'on', 2 => 'on' ]); // 1 or 2
$value = new SetCriterionValue([ 1, 2 ]);                   // 1 or 2

SetCriterionValue 实例也可以用作字符串。

<?php

use ICanBoogie\Facets\CriterionValue\SetCriterionValue;

echo new SetCriterionValue([ 1, 2, 3 ]); // "1|2|3"
echo new SetCriterionValue([ 1 ]);       // "1"
echo new SetCriterionValue([ ]);         // ""

SetCriterionValue 实例可以在修改查询时由准则用来创建 IN(?) 条件。

将准则与模型关联

准则是通过 activerecord 配置片段和 facets 键与模型关联的。模型的准则使用模型的标识符指定。从片段中合成了 activerecord_facets 配置。包通过将 criteriacriterion_list 获取器添加到 Model 类来实现,分别用来检索配置准则和与模型关联的 CriterionList 实例。

注意: 此功能目前需要 ICanBoogie 框架和 icanboogie/bind-facets 包。可以使用仅包含 icanboogie/prototype 包的类似功能实现。在这种情况下,您只需要为 Model 类定义 criteriacriterion_list 获取器。

以下示例演示了如何将 nidslug 条件与 nodes 模型关联,以及如何将 monthyear 条件与 articles 模型关联。

<?php

// config/activerecord.php

return [

    'facets' => [

        'nodes' => [

            'nid' => Icybee\Modules\Nodes\NidCriterion::class,
            'slug' => Icybee\Modules\Nodes\SlugCriterion::class

        ],

        'articles' => [

            'month' => Icybee\Modules\Articles\MonthCriterion::class,
            'year' => Icybee\Modules\Articles\YearCriterion::class

        ]

    ]

];

请注意,条件是可以继承的。在我们的示例中,因为 articles 继承了 nodes,所以它继承了其 nidslug 条件。

获取与模型关联的条件

可以使用包添加的 criteria 获取器从模型中检索条件数组。获取器返回的条件和继承条件是在 activerecord_facets 配置中定义的。

<?php

use ICanBoogie\ActiveRecord;

$model = ActiveRecord\get_model('articles');

array_keys($model->criteria);
# [ 'nid', 'slug', 'month', 'year' ]

criteriacriterion_list 获取器添加到了 Model 类中

获取与模型关联的 CriterionList 实例

可以使用包添加的 criterion_list 获取器从模型中检索与模型关联的 CriterionList 实例。获取器返回的是通过 criteria 获取器获取的条件创建的 CriterionList 实例。

<?php

$criterion_list = $model->criterion_list;

要求

此包需要 PHP 5.5 或更高版本。

安装

composer require icanboogie/facets

文档

此包作为 ICanBoogie 框架的一部分进行了文档记录。文档。您可以使用 make doc 命令生成包及其依赖的文档。文档生成在 build/docs 目录中。需要 ApiGen。可以使用 make clean 命令清理该目录。

测试

运行 make test-container 以创建并登录到测试容器,然后运行 make test 以运行测试套件。或者,运行 make test-coverage 以带有测试覆盖率的运行测试套件。打开 build/coverage/index.html 以查看代码覆盖率的分解。

许可证

icanboogie/facets新BSD许可证 下发布。