定制 technically/search-query 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

technically/search-query

Composer 安装命令:

composer require technically/search-query

包简介

Parse plaintext search queries into easy-to-use structures

README 文档

README

🔍 Parse plaintext search queries into easy-to-use filter structures.

This library takes a human-typed search query string and parses it into a structured Query object containing typed filters (KeywordFilter, FieldFilter). It supports quoted strings, negation, comparison operators, and field-based filtering.

Test

Installation

composer require technically/search-query

Requirements:

  • PHP 8.4+

Quick Start

use Technically\SearchQuery\QueryParser;

$parser = new QueryParser();
$query  = $parser->parse('tag:php -legacy "best practices"');

foreach ($query->filters as $filter) {
    // Filter instances...
}

Supported Query Syntax

Syntax Parsed As
hello KeywordFilter('hello')
"hello world" KeywordFilter('hello world', quoted: true)
-hello KeywordFilter('hello', exclude: true)
tag:php FieldFilter('tag', ':', 'php')
-tag:php FieldFilter('tag', ':', 'php', exclude: true)
year>2020 FieldFilter('year', '>', '2020')
year>=2020 FieldFilter('year', '>=', '2020')
year<2020 FieldFilter('year', '<', '2020')
year<=2020 FieldFilter('year', '<=', '2020')
hello\ world KeywordFilter('hello world') (escaped whitespace)
"custom field":value FieldFilter('custom field', ':', 'value')

Negation

A leading - (minus) before a keyword or field filter negates it. Multiple minuses are gracefully collapsed into a single negation.

-apple                    -> KeywordFilter('apple', exclude: true)
-tag:legacy               -> FieldFilter('tag', ':', 'legacy', exclude: true)

Quoting

Double quotes group multiple words into a single token. Quotes can be escaped with \.

"hello world"            -> KeywordFilter('hello world', quoted: true)
field:"hello world"      -> FieldFilter('field', ':', 'hello world', quoted: true)

Escaping

The backslash \ escape character works both inside and outside quoted strings:

apples\ fruits            -> KeywordFilter('apples fruits')
55\"                      -> KeywordFilter('55"')
"hello \"world\""         -> KeywordFilter('hello "world"', quoted: true)

The Tolerant Reader

The parser is built using the Tolerant Reader design pattern — to be forgiving with malformed input. It never throws.

API Reference

QueryParser

The main entry point for parsing query strings.

use Technically\SearchQuery\QueryParser;

$parser = new QueryParser();
$query  = $parser->parse('your search query');

The parser accepts an optional Tokenizer instance in its constructor. By default, it uses QueryTokenizer.

Methods

  • parse(string $query): Query — Parses a query string into a Query object.

Query

An immutable value object representing the parsed search query.

use Technically\SearchQuery\Query;

$query = new Query([
    new KeywordFilter('php'),
    new FieldFilter('tag', ':', 'tutorial'),
]);

Properties

  • public readonly array $filters — Array of Filter instances.

Methods

  • static empty(): self — Create a new empty query.
  • isEmpty(): bool — Check if the query is empty (has no filters).
  • toString(): string — Serializes the query back to the search query syntax string.

Filters

All filters implement the Technically\SearchQuery\Filters\Filter marker interface.

KeywordFilter

Represents a free-text keyword search term.

use Technically\SearchQuery\Filters\KeywordFilter;

new KeywordFilter('php');
new KeywordFilter('hello world', quoted: true);
new KeywordFilter('legacy', exclude: true);

Properties:

  • public readonly string $keyword — The keyword value.
  • public readonly bool $quoted — Whether the keyword was originally quoted.
  • public readonly bool $exclude — Whether the keyword is negated.

Methods:

  • toString(): string — Serializes the filter back to query syntax.

FieldFilter

Represents a field-based filter (field:operator:value).

use Technically\SearchQuery\Filters\FieldFilter;

new FieldFilter('year', '>', '2020');
new FieldFilter('status', ':', 'active', quoted: true);
new FieldFilter('tag', ':', 'legacy', exclude: true);

Properties:

  • public readonly string $field — The field name.
  • public readonly FilterOperator $operator — The comparison operator.
  • public readonly string $value — The filter value.
  • public readonly bool $quoted — Whether the value was originally quoted.
  • public readonly bool $exclude — Whether the filter is negated.

Methods:

  • toString(): string — Serializes the filter back to query syntax.

Examples

Parse a complex query

use Technically\SearchQuery\QueryParser;
use Technically\SearchQuery\Filters\KeywordFilter;
use Technically\SearchQuery\Filters\FieldFilter;

$parser = new QueryParser();
$query  = $parser->parse('php -legacy "best practices" year>=2020');

foreach ($query->filters as $filter) {
    if ($filter instanceof KeywordFilter) {
        echo "Keyword: {$filter->keyword}"
           . ($filter->exclude ? ' (excluded)' : '')
           . ($filter->quoted ? ' (quoted)' : '')
           . "\n";
    } elseif ($filter instanceof FieldFilter) {
        echo "Field: {$filter->field} {$filter->operator->value} {$filter->value}"
           . ($filter->exclude ? ' (excluded)' : '')
           . ($filter->quoted ? ' (quoted)' : '')
           . "\n";
    }
}
// Output:
// Keyword: php
// Keyword: legacy (excluded)
// Keyword: best practices (quoted)
// Field: year >= 2020

Serialize filters back to strings

$filter = new FieldFilter('tag', ':', 'hello world', quoted: true, exclude: true);
echo $filter->toString(); // -tag:"hello world"

// Or serialize an entire Query back to string:
$query = new Query([
    new KeywordFilter('php'),
    new FieldFilter('year', '>', '2020', exclude: true),
]);
echo $query->toString(); // php -year>2020

Custom tokenization

use Technically\SearchQuery\QueryParser;
use Technically\SearchQuery\Contracts\Tokenizer;

class MyCustomTokenizer implements Tokenizer
{
    public function tokenize(string $query): iterable
    {
        // Custom tokenization logic...
    }
}

$parser = new QueryParser(new MyCustomTokenizer());

Running Tests

composer tests

Tests are written with Pest PHP.

License

MIT

Credits

Implemented by 👾 Ivan Voskoboinyk.

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-06-15

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固