Expression Language, un nuevo componente para Symfony 2.4

Aunque estaba previsto que Symfony 2.4 fuera una versión de transición dedicada solamente a corregir errores, finalmente contendrá una nueva característica que puede cambiar significativamente la forma en la que se crean aplicaciones Symfony.

Esta nueva característica se basa en el componente Expression Language, que es un motor para compilar y evaluar expresiones. Se trata de una versión simplificada del motor de expresiones que utiliza Twig. A continuación se muestra el caso de uso más sencillo de este nuevo componente:

$expresion = new ExpressionLanguage();
echo $expresion->evaluate('1 + 1');  // resultado : 2
echo $expresion->compile('1 + 2');   // resultado : "(1 + 2)"

Por el momento, este componente soporta los siguientes elementos dentro de las expresiones:

  • Todos los operadores matemáticos (teniendo en cuenta la prioridad de cada uno): unarios (not, !, -, +) y binarios (or, ||, and, &&, b-or, b-xor, b-and, ==, ===, !=, !==, <, >, >=, <=, not in, in, .., +, -, ~, /, %, *).
  • Cadenas de texto, números, arrays ([1, 2]), hashes ({ a: "b" }), booleanos y null.
  • Acceso a variables (usuario), arrays (usuarios[1]), propiedades (usuario.nombre) y métodos (usuario.getFactura(1)).
  • Otros: el operador ternario (a ? b : c) y las constantes (constant('NUM')).
  • Cualquier combinación de todo lo anterior.

En cualquier caso, donde realmente pueden ser más útiles las expresiones es cuando se combinan con otros componentes de Symfony. El siguiente ejemplo muestra cómo utilizar una expresión (<argument type="expression"> ... </argument>) para establecer el valor de un argumento en el contenedor de servicios:

<parameters>
    <parameter key="value">foobar</parameter>
</parameters>
<services>
    <service id="foo" class="Foo">
        <argument type="expression">
            service('bar').getvalue(parameter('value'))
        </argument>
    </service>
    <service id="bar" class="Bar" />
</services>

Para simplificar las expresiones, el componente Expression Language añade las funciones service() (obtiene el servicio cuyo ID se indica) y parameter() (optiene el valor del parámetro cuyo ID se indica).

En el componente de seguridad, se puede restringir el acceso mediante expresiones y la nueva opción allow_if:

access_control:
    - { path: ^/_internal/secure,
        allow_if: "'127.0.0.1' == request.getClientIp() or has_role('ROLE_ADMIN')" }

En este caso, de nuevo se definen variables especiales para simplificar las expresiones: request (obtiene el objeto de la petición), token (obtiene el token del componente de seguridad), user (obtiene el objeto que representa al usuario), etc.

El enrutamiento de Symfony es uno de los componentes que más se puede beneficiar de estas expresiones. Hasta ahora, las condiciones que puedes añadir a las rutas están restringidas a las variables especiales de Symfony (_format, methods, etc.) y a las partes variables de la ruta (mediante la propiedad requirements). Gracias a la nueva propiedad condition, puedes definir condiciones basadas en cualquier información de la petición del usuario. Este ejemplo muestra cómo restringir una ruta para que sólo funcione con los métodos GET y HEAD en el navegador Firefox:

ruta:
    path: /hola/{nombre}
    condition: "context.getMethod() in ['GET', 'HEAD']
                and request.headers.get('User-Agent') =~ '/firefox/i'"

El componente de Validación también se ha integrado con las expresiones y el bundle SensioFrameworkExtraBundle ya incluye nuevas anotaciones dinámicas. Así que pronto podrás utilizar lo siguiente en tus aplicaciones Symfony:

/**
 * @Route("/post/{id}")
 * @Cache(smaxage="15", lastModified="post.getUpdatedAt()",
          ETag="'Post' ~ post.getId() ~ post.getUpdatedAt()")
 * @Security("has_role('ROLE_ADMIN')")
 */
public function showAction(Post $post)
{
}

La propuesta de crear el componente Expression Language y de integrarlo con los diferentes componentes de Symfony ha creado una gran polémica en los últimos días. Estos son algunos de los argumentos esgrimidos a favor y en contra del nuevo componente:

En contra

  • Introduce demasiada magia.
  • Las aplicaciones serán más difíciles de testear y de depurar.
  • Aunque no es código, pueden tener código y se escriben fuera del código (anotaciones, archivos de configuración).

A favor

  • Permiten que los archivos de configuración YAML/XML sean dinámicos.
  • Ofrecen una flexibilidad que ahora mismo es imposible de conseguir con Symfony (ver ejemplo anterior sobre enrutamiento).
  • Son opcionales. Si no te gustan, no las uses.

El componente Expression Language todavía no tiene documentación, pero esta semana lo conoceremos más en detalle gracias a la charla que dará Fabien Potencier en la conferencia Symfony Live London 2013.

Más información

Comentarios

  1. ¡Hola! Una duda, el titular habla de Expression Engine, ¿se trata de lo que luego nombras como Expression Language o es una errata y tenías en la cabeza el CMS?

    En cualquier caso, es una interesantísima funcionalidad.

    Manuel GM el 17 de septiembre de 2013, 20:11:39

  2. ¡Hola! Una duda, el titular habla de Expression Engine, ¿se trata de lo que luego nombras como Expression Language o es una errata y tenías en la cabeza el CMS?

    En cualquier caso, es una interesantísima funcionalidad :)

    Manuel GM el 17 de septiembre de 2013, 20:11:47

  3. @Manuel, en efecto el titular estaba mal y el nombre correcto del componente es Expression Language. Me he liado porque el nombre original del componente era Expression Engine, hasta que Fabien decidió cambiarlo precisamente para no confundirlo con el famoso CMS.

    Javier Eguiluz el 18 de septiembre de 2013, 8:14:58

Este artículo ya no permite añadir más comentarios.
¿Por qué? Los artículos cierran sus comentarios automáticamente unos meses después de su publicación para asegurar que estos sigan siendo relevantes.

Publicada el

17 de septiembre de 2013

Proyectos Symfony destacados

La plataforma de eCommerce 100% Symfony que rivaliza con Magento y PrestaShop. Ver más

Síguenos en @symfony_es para acceder a las últimas noticias.