Expression Language is a new awesome component that got released in the latest Symfony2.4. This component allows string expressions to be parsed, compiled and evaluated in PHP. It was basically extracted from the Twig library that supports writing expression logic in templates.
As simple as:–
The previous code will output “2”!
It seems simple enough, but the benefits that it introduces are great! Especially when we talk about a company like Namshi, where there are dedicated and specialized content and marketing teams with hundreds of templates and segments of information that must be delivered and shown on the website. The goal is to provide the most flexibility to other departments in creating their information with the least overhead in terms of code maintenance to the development team.
Fabien Potencier, the creator of Symfony, points out that one of the advantages of introducing this component will be the ability to overcome the limitation of the “static configuration” anywhere in the Symfony2 application such as in services and routing. Imagine that instead of having one route to point to a controller, you can give an expression that sends the request of the same path to different controllers DYNAMICALLY! More explanation about this is introduced here.
So, let’s take a look on this component in some more detail.
The component supports a set of pre-defined operators and functions that can be used to construct complex expressions, we list them and their PHP counterparts:–
1. binary operators and functions - '**' => 'pow' - '..' => 'range' - 'in' => 'in_array' - 'not in' => '!in_array' - '&& || | ^ & == === != !== < > >= <= + = * / %' => same in php - 'A matches B' => preg_match(A,B) 2. Unary operators - '!' => '!' - 'not' => '!' - '+' => '+' - '-' => '-' 3. Object Attributes - 'foo.one' => 'foo->one' 4. Arrays - '[foo1,foo2]' => array("foo1", "foo2") 5. Functions - 'foo(a,b,c)' => call_user_func_array(array(foo), array(a, b, c) 6. Names: - 'foo' => $foo
The killer feature is, as we are going to see next, is the ability to register your own functions (similar to Twig) in the component to be utilized in expressions.
The component provides public access to methods that allows you to create your own implementations of expression functions.
As its name implies, this function registers or adds the required support to call a function within the expression string. This method has two callback functions, one to be called when the expression is compiled, and the other when its evaluated.
This method, returns the equivalent PHP expression without evaluating it, so you can evaluate it after doing some required manipulation.
This function both compiles the expression to PHP and evaluates it to return the outcome. The expression is evaluated for both the built in functions and operators and the evaluate callback function
of a registered custom function.
It also allows to send a set of default predefined
$values to the evaluation process to be passed to the evaluate callback.
This function parses a string expression from a Token Stream to a Node Tree (the component is built using the Abstract Syntax Tree algorithm) so you can have your expression as a tree of nodes. Not really sure how it can be benefited from (please share your ideas!).
In a simple
var_dump() I can show you what this method can return
It can perhaps be used to give flexibility for developers to inject and manipulate expressions coming from a non-configurable source.
Here is a comprehensive example of all the previously described methods:
Since here at Namshi we are using Symfony2 as the main PHP framework for our Backend and API development efforts. We are up-to-date with latest releases from Symfony. The Expression Language Component allowed us to introduce more flexibility in the way other departments such as Content and Marketing tailor views and serve data based on some client related information.
We were able to integrate Twig, YAML and the Expression Language Component using Redis as the mega storage unit.
As an example, we have a set of Twig templates for the SEO guys to store the pages’ meta information stored in a redis hash and indexed by the path info of the request, and they are json encoded:
And in a
device redis hash, we have the corresponding possible values for
device indexed by the device type
Now, we fetch the appropriate template based on the path info and select the first template that its condition evaluates to
true, fetch the context (device) based on
client information, render the twig template with the appropriate device value and parse it as YAML!
Was that fast? sorry, here is a sample code:
Nice, easy and simple. This approach for a CMS like system, provides the following benefits:
- High flexibility in creating information (content, SEO, etc..)
- Tailoring data according to client information (mobile, desktop, large/small screens, app, tablet, etc..)
- Can be based on numerous variables (path information, headers, domain, device type, etc..)
- Content specialization and less dependency on the tech team.
- Less code maintenance overhead since the expected future requirements can only be limited to registering Expression Language functions.