diff --git a/CHANGELOG b/CHANGELOG index 341de4843..a78532999 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,6 @@ # 3.22.2 (2026-XX-XX) - * n/a + * Add `===` and `!==` operators (equivalent to the `same as` and `not same as` tests) # 3.22.2 (2025-12-14) diff --git a/doc/operators_precedence.rst b/doc/operators_precedence.rst index 472e39529..c4e9fc514 100644 --- a/doc/operators_precedence.rst +++ b/doc/operators_precedence.rst @@ -72,6 +72,10 @@ +------------+------------------+---------+---------------+-------------------------------------------------------------------+ | | ``has every`` | | | | +------------+------------------+---------+---------------+-------------------------------------------------------------------+ +| | ``===`` | | | | ++------------+------------------+---------+---------------+-------------------------------------------------------------------+ +| | ``!==`` | | | | ++------------+------------------+---------+---------------+-------------------------------------------------------------------+ | 18 | ``b-and`` | infix | Left | | +------------+------------------+---------+---------------+-------------------------------------------------------------------+ | 17 | ``b-xor`` | infix | Left | | @@ -170,6 +174,10 @@ Here is the same table for Twig 4.0 with adjusted precedences: +------------+------------------+---------+---------------+-------------------------------------------------------------------+ | | ``has every`` | | | | +------------+------------------+---------+---------------+-------------------------------------------------------------------+ +| | ``===`` | | | | ++------------+------------------+---------+---------------+-------------------------------------------------------------------+ +| | ``!==`` | | | | ++------------+------------------+---------+---------------+-------------------------------------------------------------------+ | 18 | ``b-and`` | infix | Left | | +------------+------------------+---------+---------------+-------------------------------------------------------------------+ | 17 | ``b-xor`` | infix | Left | | diff --git a/doc/templates.rst b/doc/templates.rst index ad281e4e6..fe0b1825b 100644 --- a/doc/templates.rst +++ b/doc/templates.rst @@ -722,6 +722,9 @@ Comparisons The following mathematical comparison operators are supported in any expression: ``==``, ``!=``, ``<``, ``>``, ``>=``, and ``<=``. +In addition, the ``===`` and ``!==`` strict comparison operators are supported +(they are equivalent to the ``same as`` and ``not same as`` tests). + Spaceship Operator ~~~~~~~~~~~~~~~~~~ diff --git a/src/ExpressionParser/Prefix/LiteralExpressionParser.php b/src/ExpressionParser/Prefix/LiteralExpressionParser.php index d98c9adf1..3ffd39786 100644 --- a/src/ExpressionParser/Prefix/LiteralExpressionParser.php +++ b/src/ExpressionParser/Prefix/LiteralExpressionParser.php @@ -100,10 +100,6 @@ final class LiteralExpressionParser extends AbstractExpressionParser implements return new ContextVariable($token->getValue(), $token->getLine()); } - if ('=' === $token->getValue() && ('==' === $stream->look(-1)->getValue() || '!=' === $stream->look(-1)->getValue())) { - throw new SyntaxError(\sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $stream->getSourceContext()); - } - // no break default: throw new SyntaxError(\sprintf('Unexpected token "%s" of value "%s".', $token->toEnglish(), $token->getValue()), $token->getLine(), $stream->getSourceContext()); diff --git a/src/Extension/CoreExtension.php b/src/Extension/CoreExtension.php index 8e11be832..061cd5684 100644 --- a/src/Extension/CoreExtension.php +++ b/src/Extension/CoreExtension.php @@ -55,10 +55,12 @@ use Twig\Node\Expression\Binary\ModBinary; use Twig\Node\Expression\Binary\MulBinary; use Twig\Node\Expression\Binary\NotEqualBinary; use Twig\Node\Expression\Binary\NotInBinary; +use Twig\Node\Expression\Binary\NotSameAsBinary; use Twig\Node\Expression\Binary\NullCoalesceBinary; use Twig\Node\Expression\Binary\OrBinary; use Twig\Node\Expression\Binary\PowerBinary; use Twig\Node\Expression\Binary\RangeBinary; +use Twig\Node\Expression\Binary\SameAsBinary; use Twig\Node\Expression\Binary\SpaceshipBinary; use Twig\Node\Expression\Binary\StartsWithBinary; use Twig\Node\Expression\Binary\SubBinary; @@ -360,6 +362,8 @@ final class CoreExtension extends AbstractExtension new BinaryOperatorExpressionParser(EndsWithBinary::class, 'ends with', 20), new BinaryOperatorExpressionParser(HasSomeBinary::class, 'has some', 20), new BinaryOperatorExpressionParser(HasEveryBinary::class, 'has every', 20), + new BinaryOperatorExpressionParser(SameAsBinary::class, '===', 20), + new BinaryOperatorExpressionParser(NotSameAsBinary::class, '!==', 20), new BinaryOperatorExpressionParser(RangeBinary::class, '..', 25), new BinaryOperatorExpressionParser(AddBinary::class, '+', 30), new BinaryOperatorExpressionParser(SubBinary::class, '-', 30), diff --git a/src/Node/Expression/Binary/NotSameAsBinary.php b/src/Node/Expression/Binary/NotSameAsBinary.php new file mode 100644 index 000000000..ed28c19bb --- /dev/null +++ b/src/Node/Expression/Binary/NotSameAsBinary.php @@ -0,0 +1,23 @@ +raw('!=='); + } +} diff --git a/src/Node/Expression/Binary/SameAsBinary.php b/src/Node/Expression/Binary/SameAsBinary.php new file mode 100644 index 000000000..b08a19072 --- /dev/null +++ b/src/Node/Expression/Binary/SameAsBinary.php @@ -0,0 +1,23 @@ +raw('==='); + } +} diff --git a/tests/Fixtures/exceptions/strict_comparison_operator.test b/tests/Fixtures/exceptions/strict_comparison_operator.test deleted file mode 100644 index e14beb672..000000000 --- a/tests/Fixtures/exceptions/strict_comparison_operator.test +++ /dev/null @@ -1,6 +0,0 @@ ---TEST-- -The PHP === strict comparison operator is not supported ---TEMPLATE-- -{{ 1 === 2 }} ---EXCEPTION-- -Twig\Error\SyntaxError: Unexpected operator of value "=". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead in "index.twig" at line 2. diff --git a/tests/Fixtures/expressions/sameas.test b/tests/Fixtures/expressions/sameas.test index b4fdaa212..79ace4ae4 100644 --- a/tests/Fixtures/expressions/sameas.test +++ b/tests/Fixtures/expressions/sameas.test @@ -3,10 +3,12 @@ Twig supports the "same as" operator --TEMPLATE-- {{ 1 is same as(1) ? 'OK' }} {{ 1 is same as 1 ? 'OK' }} +{{ 1 === 1 ? 'OK' }} + {{ 1 is not same as(true) ? 'OK' }} {{ 1 is not same as true ? 'OK' }} -{{ 1 is same as(1) ? 'OK' }} -{{ 1 is not same as(true) ? 'OK' }} +{{ 1 !== true ? 'OK' }} + {{ 1 is same as (1) ? 'OK' }} {{ 1 is same as 1 ? 'OK' }} {{ 1 is not same as '1' ? 'OK' }} @@ -20,9 +22,11 @@ return [] OK OK OK -OK -OK -OK + +OK +OK +OK + OK OK OK