Новое в Symfony 5.1: Валидатор ExpressionLanguage

Компонент ExpressionLanguage предоставляет механизм для компиляции и оценки выражений. Он используется многими компаниями, чтобы позволить не разработчикам писать бизнес-правила (например, оценить следующее выражение, чтобы решить, предлагает ли ваш магазин скидку: 'user ["isActive"] == true and product ["price"]> 20').

В Symfony 5.1 улучшили компонент ExpressionLanguage, чтобы позволить проверять выражения без их анализа или оценки. Классы ExpressionLanguage и Parser теперь включают метод lint() для проверки выражений:

use Symfony\Component\ExpressionLanguage\Lexer;
use Symfony\Component\ExpressionLanguage\Parser;

$lexer = new Lexer();
$parser = new Parser([]);
$parser->lint($lexer->tokenize($expression), $allowedVariableNames);

$expression = 'foo["some_key"].callFunction(a ? b)';
$allowedVariableNames = ['foo', 'a', 'b'];
// Result: no error; expression is valid.

$expression = 'foo["some_key")';
$allowedVariableNames = ['foo'];
// Result: Unclosed "[" around position 3 for expression `foo["some_key")`.

$expression = '{key: foo key2: bar}';
$allowedVariableNames = ['foo', 'bar'];
// Result: A hash value must be followed by a comma
//         Unexpected token "name" of value "key2" ("punctuation" expected with value ",")
//         around position 11 for expression `{key: foo key2: bar}`.

Помимо использования этих методов lint(), вы также можете использовать новое ограничение ExpressionLanguageSyntax, чтобы проверить, что значение, сохраненное в каком-либо свойстве, определяет допустимый синтаксис ExpressionLanguage (вы также можете дополнительно проверить имена переменных выражения):

namespace App\Entity;

use Symfony\Component\Validator\Constraints as Assert;

class Order
{
    /**
     * @Assert\ExpressionLanguageSyntax()
     */
    protected $promotion;

    /**
     * @Assert\ExpressionLanguageSyntax(
     *     names = ['user', 'shipping_centers'],
     *     validateNames = true
     * )
     */
    protected $shippingOptions;
}