From e9a81bfdf19aac7dc4f85f90d01efc65101bbbf8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Sat, 16 Nov 2013 19:06:59 -0600 Subject: [PATCH 1/2] [#3044] Furthering @WouterJ's work on the ExpressionLanguage component This adds more examples, details about how to pass in variables, and working with objects/arrays --- .../expression_language/introduction.rst | 69 ++++++- components/expression_language/syntax.rst | 181 ++++++++++++++++-- 2 files changed, 230 insertions(+), 20 deletions(-) diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index a7f474c732a..da23a869e0f 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -10,24 +10,51 @@ 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 added 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`_). +* 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. In the Symfony2 Framework, for example, +expressions can be used 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`` statements. 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: @@ -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..4cc7da1192b 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -9,24 +9,102 @@ 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, + ) + ); + +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 +113,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 +158,95 @@ 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, + ) + ); + +These would both return ``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 would return ``true``. + String Operators -................ +~~~~~~~~~~~~~~~~ * ``~`` (concatenation) +For example:: + + $ret4 = $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'; + + $ret5 = $language->evaluate( + 'user.group in ["human_resources", "marketing"]', + array( + 'user' => $user + ) + ); + Numeric Operators -................. +~~~~~~~~~~~~~~~~~ * ``..`` (range) Ternary Operators -................. +~~~~~~~~~~~~~~~~~ * ``foo ? 'yes' : 'no'`` * ``foo ?: 'no'`` (equal to ``foo ? foo : 'no'``) From a14c39d530eb1ab4e520c49b3bf7ded8c3c9b07b Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 28 Nov 2013 11:16:51 -0600 Subject: [PATCH 2/2] [#3191] Many tweaks to expression language component thanks to @WouterJ, @xabbuh and @cordoval. Thanks guys! --- components/expression_language/introduction.rst | 16 ++++++++-------- components/expression_language/syntax.rst | 14 +++++++++----- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/components/expression_language/introduction.rst b/components/expression_language/introduction.rst index da23a869e0f..7cdabf56bf1 100644 --- a/components/expression_language/introduction.rst +++ b/components/expression_language/introduction.rst @@ -10,22 +10,22 @@ The ExpressionLanguage Component (mostly, but not limited to, Booleans). .. versionadded:: 2.4 - The ExpressionLanguage component was added in Symfony 2.4. + The ExpressionLanguage component was introduced in Symfony 2.4. Installation ------------ You can install the component in 2 different ways: -* :doc:`Install it via Composer ` (``symfony/expression-language`` on `Packagist`_). -* Use the official Git repository (https://github.com/symfony/expression-language); +* :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. In the Symfony2 Framework, for example, -expressions can be used in security, for validation rules, and in route matching. +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*. @@ -52,15 +52,15 @@ Usage The ExpressionLanguage component can compile and evaluate expressions. Expressions are one-liners that often return a Boolean, which can be used -by the code executing the expression in an ``if`` statements. A simple example +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`:: diff --git a/components/expression_language/syntax.rst b/components/expression_language/syntax.rst index 4cc7da1192b..49a80d46082 100644 --- a/components/expression_language/syntax.rst +++ b/components/expression_language/syntax.rst @@ -49,6 +49,8 @@ to JavaScript:: ) ); +This will print ``Honeycrisp``; + Calling Methods ~~~~~~~~~~~~~~~ @@ -77,7 +79,7 @@ JavaScript:: ) ); -This will print "Hi Hi Hi!"; +This will print ``Hi Hi Hi!``. .. _component-expression-arrays: @@ -178,7 +180,7 @@ Examples:: ) ); -These would both return ``false``. +Both variables would be set to ``false``. Logical Operators ~~~~~~~~~~~~~~~~~ @@ -198,7 +200,7 @@ For example:: ) ); -This would return ``true``. +This ``$ret`` variable will be set to ``true``. String Operators ~~~~~~~~~~~~~~~~ @@ -207,7 +209,7 @@ String Operators For example:: - $ret4 = $language->evaluate( + echo $language->evaluate( 'firstName~" "~lastName', array( 'firstName' => 'Arthur', @@ -233,13 +235,15 @@ For example:: $user = new User(); $user->group = 'human_resources'; - $ret5 = $language->evaluate( + $inGroup = $language->evaluate( 'user.group in ["human_resources", "marketing"]', array( 'user' => $user ) ); +The ``$inGroup`` would evaluate to ``true``. + Numeric Operators ~~~~~~~~~~~~~~~~~