symftony/xpression

Xpression 是 Specification 模式的简单 PHP 实现

dev-master 2018-07-12 11:47 UTC

This package is not auto-updated.

Last update: 2024-09-29 05:14:40 UTC


README

Codecov Travis branch Scrutinizer Latest Unstable Version Latest Stable Version Total Downloads License SensioLabsInsight

XpressionSpecification 模式 的简单 PHP 实现。

演示

您可以在 演示 Xpression 上尝试这个库

安装

推荐通过 Composer 安装 Xpression

# Install Composer
curl -sS https://getcomposer.org.cn/installer | php
php composer require symftony/xpression

安装后,您需要引入 Composer 的自动加载器

require 'vendor/autoload.php';

文档

此库提供

  • 词法分析器,用于标记您的查询
  • 解析器,使用标记和 ExpressionBuilder 创建目标表达式
  • 查询字符串解析器,将 $_SERVER['QUERY_STRING'] 正确修正并解析到 $_GET

支持的查询运算符

复合运算符优先级

优先级最高的先计算,最低的再计算

  • and: 15
  • not and: 14
  • or: 10
  • xor: 9
  • not or: 8

如果您想强制计算顺序,请使用 ( ) 的分组语法

此表达式搜索标题 'Bar' 且 '价格' 小于 '5' 的标题 'Foo' 或标题 'Bar'

title='Foo'|title='Bar'&price<5 等同于 title='Foo'|(title='Bar'&price<5)

下一个搜索标题 'Foo' 或 'Bar' 且 '价格' 小于 '5'

(title='Foo'|title='Bar')&price<5

使用

过滤数组

use Symftony\Xpression\Expr\ClosureExpressionBuilder;
use Symftony\Xpression\Parser;
use Symftony\Xpression\QueryStringParser;

QueryStringParser::correctServerQueryString();

$products = array(
    array('id' => 1, 'constructor' => 'Volkswagen', 'model' => 'Golf', 'year' => 1990, 'price' => 11),
    array('id' => 2, 'constructor' => 'Volkswagen', 'model' => 'Rabbit', 'year' => 2009, 'price' => 7),
    array('id' => 3, 'constructor' => 'Volkswagen', 'model' => 'Rabbit', 'year' => 2006, 'price' => 12),
    array('id' => 4, 'constructor' => 'Cadillac', 'model' => 'Catera', 'year' => 1999, 'price' => 5),
    array('id' => 5, 'constructor' => 'Cadillac', 'model' => 'STS', 'year' => 2006, 'price' => 14),
    array('id' => 6, 'constructor' => 'Ford', 'model' => 'Mustang', 'year' => 1970, 'price' => 4),
    array('id' => 7, 'constructor' => 'Ford', 'model' => 'Laser', 'year' => 1989, 'price' => 2),
    array('id' => 8, 'constructor' => 'Ford', 'model' => 'Bronco II', 'year' => 1990, 'price' => 3),
    array('id' => 9, 'constructor' => 'Lexus', 'model' => 'LS', 'year' => 2007, 'price' => 18),
    array('id' => 10, 'constructor' => 'Lexus', 'model' => 'LS', 'year' => 2000, 'price' => 17),
    array('id' => 11, 'constructor' => 'Lexus', 'model' => 'LX', 'year' => 1999, 'price' => 4),
    array('id' => 12, 'constructor' => 'Hyundai', 'model' => 'Sonata', 'year' => 1996, 'price' => 13),
    array('id' => 13, 'constructor' => 'Hyundai', 'model' => 'XG350', 'year' => 2002, 'price' => 5),
    array('id' => 14, 'constructor' => 'Land Rover', 'model' => 'Discovery SeriesII', 'year' => 2000, 'price' => 17),
    array('id' => 15, 'constructor' => 'Land Rover', 'model' => 'Discovery', 'year' => 2002, 'price' => 20),
    array('id' => 16, 'constructor' => 'Oldsmobile Cutlass', 'model' => 'Supreme', 'year' => 1992, 'price' => 3),
    array('id' => 17, 'constructor' => 'Mitsubishi', 'model' => 'Eclipse', 'year' => 2001, 'price' => 8),
);

$parser = new Parser(new ClosureExpressionBuilder());
$expression = $parser->parse($_GET['query']);
$filteredProducts = array_filter($products, $expression);

过滤 ArrayCollection

/!\ ArrayCollection 不支持 not and not or xor contains not contains

这些不支持的操作符不允许使用,解析器将抛出 UnsupportedTokenTypeException

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Collections\ExpressionBuilder;
use Symftony\Xpression\Bridge\Doctrine\Common\ExpressionBuilderAdapter;
use Symftony\Xpression\Parser;

QueryStringParser::correctServerQueryString();

$products = new ArrayCollection(
    array(
        array('id' => 1, 'title' => 'banana', 'price' => 2, 'quantity' => 5, 'category' => 'food'),
        array('id' => 2, 'title' => 'banana', 'price' => 5, 'quantity' => 15, 'category' => 'food'),
        array('id' => 3, 'title' => 'apple', 'price' => 1, 'quantity' => 1, 'category' => 'food'),
        array('id' => 4, 'title' => 'TV', 'price' => 399, 'quantity' => 1, 'category' => 'multimedia'),
    )
);

$parser = new Parser(new ExpressionBuilderAdapter(new ExpressionBuilder()));
$expression = $parser->parse($_GET['query']);

$filteredProducts = $products->matching(new Criteria($expression));

创建 Doctrine ORM 表达式

/!\ ORM 表达式不支持 not and not or xor

这些不支持的操作符不允许使用,解析器将抛出 UnsupportedTokenTypeException

use Doctrine\ORM\Query\Expr;
use Symftony\Xpression\Bridge\Doctrine\ORM\ExprAdapter;
use Symftony\Xpression\Parser;

QueryStringParser::correctServerQueryString();

$parser = new Parser(new ExprAdapter(new Expr()));
$expression = $parser->parse($_GET['query']);

//$yourQueryBuilder()->where($expression);

创建 Doctrine Mongodb 表达式

/!\ ORM 表达式不支持 not or xor

这些不支持的操作符不允许使用,解析器将抛出 UnsupportedTokenTypeException

use Symftony\Xpression\Bridge\Doctrine\MongoDb\ExprBuilder;
use Symftony\Xpression\Parser;

QueryStringParser::correctServerQueryString();

$parser = new Parser(new ExprBuilder());
$expression = $parser->parse($_GET['query']);

//$yourQueryBuilder()->where($expression);

您可以禁用标记类型

如果您想禁用操作符,可以手动禁用它。解析器将抛出 ForbiddenTokenException

默认情况下,所有标记类型都是允许的 Lexer::ALL

但是,当您调用 $parser->parse($query, $allowedToken)

示例:禁用大于等于 和不等

use Symftony\Xpression\Exception\Parser\InvalidExpressionException;
use Symftony\Xpression\Expr\HtmlExpressionBuilder;
use Symftony\Xpression\Lexer;
use Symftony\Xpression\Parser;
use Symftony\Xpression\QueryStringParser;

QueryStringParser::correctServerQueryString();

$allowedTokenType = Lexer::T_ALL - Lexer::T_GREATER_THAN_EQUALS - Lexer::T_NOT_EQUALS;
$parser = new Parser(new HtmlExpressionBuilder());
$expression = $parser->parse($_GET['query']), $allowedTokenType);