diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index a7f474c732a..7cdabf56bf1 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -10,30 +10,57 @@ The ExpressionLanguage Component (mostly, but not limited to, Booleans). .. versionadded:: 2.4 - The ExpressionLanguage component was new in Symfony 2.4. + The ExpressionLanguage component was introduced in Symfony 2.4. Installation ------------ You can install the component in 2 different ways: -* Use the official Git repository (https://github.com/symfony/expression-language); -* :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_). +* :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_); +* Use the official Git repository (https://github.com/symfony/expression-language). + +How can the Expression Engine Help Me? +-------------------------------------- + +The purpose of the component is to allow users to use expressions inside +configuration for more complex logic. For some examples, the Symfony2 Framework +uses expressions in security, for validation rules and in route matching. + +Besides using the component in the framework itself, the ExpressionLanguage +component is a perfect candidate for the foundation of a *business rule engine*. +The idea is to let the webmaster of a website configure things in a dynamic +way without using PHP and without introducing security problems: + +.. code-block:: text + + # Get the special price if + user.getGroup() in ['good_customers', 'collaborator'] + + # Promote article to the homepage when + article.commentCount > 100 and article.category not in ["misc"] + + # Send an alert when + product.stock < 15 + +Expressions can be seen as a very restricted PHP sandbox and are immune to +external injections as you must explicitly declare which variables are available +in an expression. Usage ----- The ExpressionLanguage component can compile and evaluate expressions. -Expressions are one-liners which most of the time return a boolean, you can -compare them to the expression in an ``if`` statement. A simple example of an -expression is ``1 + 2``. You can also use more complicated expressions, such -as ``someArray[3].someMethod('bar')``. +Expressions are one-liners that often return a Boolean, which can be used +by the code executing the expression in an ``if`` statement. A simple example +of an expression is ``1 + 2``. You can also use more complicated expressions, +such as ``someArray[3].someMethod('bar')``. The component provides 2 ways to work with expressions: +* **evaluation**: the expression is evaluated without being compiled to PHP; * **compile**: the expression is compiled to PHP, so it can be cached and - evaluated; -* **evaluation**: the expression is evaluated without being compiled to PHP. + evaluated. The main class of the component is :class:`Symfony\\Component\\ExpressionLanguage\\ExpressionLanguage`:: @@ -49,7 +76,35 @@ The main class of the component is Expression Syntax ----------------- -See ":doc:`/components/expression_language/syntax`" to learn the syntax of the +See :doc:`/components/expression_language/syntax` to learn the syntax of the ExpressionLanguage component. +Passing in Variables +-------------------- + +You can also pass variables into the expression, which can be of any valid +PHP type (including objects):: + + use Symfony\Component\ExpressionLanguage\ExpressionLanguage; + + $language = new ExpressionLanguage(); + + class Apple + { + public $variety; + } + + $apple = new Apple(); + $apple->variety = 'Honeycrisp'; + + echo $language->evaluate( + 'fruit.variety', + array( + 'fruit' => $apple, + ) + ); + +This will print "Honeycrisp". For more information, see the :doc:`/components/expression_language/syntax` +entry, especially :ref:`component-expression-objects` and :ref:`component-expression-arrays`. + .. _Packagist: https://packagist.org/packages/symfony/expression-language diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 7c3a59fccb9..49a80d46082 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -9,24 +9,104 @@ expression syntax of Twig. In this document, you can find all supported syntaxes. Supported Literals -~~~~~~~~~~~~~~~~~~ +------------------ The component supports: * **strings** - single and double quotes (e.g. ``'hello'``) * **numbers** - e.g. ``103`` -* **arrays** - using twig notation (e.g. ``[1, 2]``) -* **hashes** - using twig notation (e.g. ``{ foo: 'bar' }``) +* **arrays** - using JSON-like notation (e.g. ``[1, 2]``) +* **hashes** - using JSON-like notation (e.g. ``{ foo: 'bar' }``) * **booleans** - ``true`` and ``false`` * **null** - ``null`` +.. _component-expression-objects: + +Working with Objects +-------------------- + +When passing objects into an expression, you can use different syntaxes to +access properties and call methods on the object. + +Accessing Public Methods +~~~~~~~~~~~~~~~~~~~~~~~~ + +Public properties on objects can be accessed by using the ``.`` syntax, similar +to JavaScript:: + + class Apple + { + public $variety; + } + + $apple = new Apple(); + $apple->variety = 'Honeycrisp'; + + echo $language->evaluate( + 'fruit.variety', + array( + 'fruit' => $apple, + ) + ); + +This will print ``Honeycrisp``; + +Calling Methods +~~~~~~~~~~~~~~~ + +The ``.`` syntax can also be used to call methods on an object, similar to +JavaScript:: + + class Robot + { + public function sayHi($times) + { + $greetings = array(); + for ($i = 0; $i < $times; $i++) { + $greetings[] = 'Hi'; + } + + return implode(' ', $greetings).'!'; + } + } + + $robot = new Robot(); + + echo $language->evaluate( + 'robot.sayHi(3)', + array( + 'robot' => $robot, + ) + ); + +This will print ``Hi Hi Hi!``. + +.. _component-expression-arrays: + +Working with Arrays +------------------- + +If you pass an array into an expression, use the ``[]`` syntax to access +array keys, similar to JavaScript:: + + $data = array('life' => 10, 'universe' => 10, 'everything' => 22); + + echo $language->evaluate( + 'data["life"] + data["universe"] + data["everything"]', + array( + 'data' => $data, + ) + ); + +This will print ``42``. + Supported Operators -~~~~~~~~~~~~~~~~~~~ +------------------- The component comes with a lot of operators: Arithmetic Operators -.................... +~~~~~~~~~~~~~~~~~~~~ * ``+`` (addition) * ``-`` (subtraction) @@ -35,20 +115,33 @@ Arithmetic Operators * ``%`` (modulus) * ``**`` (pow) +For example:: + + echo $language->evaluate( + 'life + universe + everything', + array( + 'life' => 10, + 'universe' => 10, + 'everything' => 22, + ) + ); + +This will print out ``42``. + Assignment Operators -.................... +~~~~~~~~~~~~~~~~~~~~ * ``=`` Bitwise Operators -................. +~~~~~~~~~~~~~~~~~ * ``&`` (and) * ``|`` (or) * ``^`` (xor) Comparison Operators -.................... +~~~~~~~~~~~~~~~~~~~~ * ``==`` (equal) * ``===`` (identical) @@ -67,31 +160,97 @@ Comparison Operators $language->evaluate('not "foo" matches "/bar/"'); // returns true +Examples:: + + $ret1 = $language->evaluate( + 'life == everything', + array( + 'life' => 10, + 'universe' => 10, + 'everything' => 22, + ) + ); + + $ret2 = $language->evaluate( + 'life > everything', + array( + 'life' => 10, + 'universe' => 10, + 'everything' => 22, + ) + ); + +Both variables would be set to ``false``. + Logical Operators -................. +~~~~~~~~~~~~~~~~~ * ``not`` or ``!`` * ``and`` or ``&&`` * ``or`` or ``||`` +For example:: + + $ret = $language->evaluate( + 'life < universe or life < everything', + array( + 'life' => 10, + 'universe' => 10, + 'everything' => 22, + ) + ); + +This ``$ret`` variable will be set to ``true``. + String Operators -................ +~~~~~~~~~~~~~~~~ * ``~`` (concatenation) +For example:: + + echo $language->evaluate( + 'firstName~" "~lastName', + array( + 'firstName' => 'Arthur', + 'lastName' => 'Dent', + ) + ); + +This would print out ``Arthur Dent``. + Array Operators -............... +~~~~~~~~~~~~~~~ * ``in`` (contain) * ``not in`` (does not contain) +For example:: + + class User + { + public $group; + } + + $user = new User(); + $user->group = 'human_resources'; + + $inGroup = $language->evaluate( + 'user.group in ["human_resources", "marketing"]', + array( + 'user' => $user + ) + ); + +The ``$inGroup`` would evaluate to ``true``. + Numeric Operators -................. +~~~~~~~~~~~~~~~~~ * ``..`` (range) Ternary Operators -................. +~~~~~~~~~~~~~~~~~ * ``foo ? 'yes' : 'no'`` * ``foo ?: 'no'`` (equal to ``foo ? foo : 'no'``)