Cómo usar plantillas PHP en lugar de Twig

No obstante que Symfony2 de manera predeterminada usa Twig como su motor de plantillas, puedes usar código PHP simple si lo deseas. Ambos motores de plantilla son igualmente compatibles en Symfony2. Symfony2 añade algunas características interesantes en lo alto de PHP para hacer más poderosa la escritura de plantillas con PHP.

Reproduciendo plantillas PHP

Si deseas utilizar el motor de plantillas PHP, primero, asegúrate de activarlo en el archivo de configuración de tu aplicación:

  • YAML
    # app/config/config.yml
    framework:
        # ...
        templating:    { engines: ['twig', 'php'] }
    
  • XML
    <!-- app/config/config.xml -->
    <framework:config ...>
        <!-- ... -->
        <framework:templating ...>
            <framework:engine id="twig" />
            <framework:engine id="php" />
        </framework:templating>
    </framework:config>
  • PHP
    $container->loadFromExtension('framework', array(
        // ...
    
        'templating' => array(
            'engines' => array('twig', 'php'),
        ),
    ));
    

Ahora puedes reproducir una plantilla PHP en lugar de una Twig simplemente usando la extensión .php en el nombre de la plantilla en lugar de .twig. El controlador a continuación reproduce la plantilla index.html.php:

// src/Acme/HelloBundle/Controller/HelloController.php

// ...

public function indexAction($name)
{
    return $this->render('AcmeHelloBundle:Hello:index.html.php', array('name' => $name));
}

También puedes utilizar el método abreviado @Template para dibujar la plantilla predeterminada AcmeHelloBundle:Hello:index.html.php:

// src/Acme/HelloBundle/Controller/HelloController.php

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

// ...

/**
 * @Template(engine="php")
 */
public function indexAction($name)
{
    return array('name' => $name);
}

Decorando plantillas

Muy a menudo, las plantillas en un proyecto comparten elementos comunes, como los bien conocidos encabezados y pies de página. En Symfony2, nos gusta pensar en este problema de forma diferente: una plantilla se puede decorar con otra.

La plantilla index.html.php está decorada por layout.html.php, gracias a la llamada a extend():

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php -->
<?php $view->extend('AcmeHelloBundle::layout.html.php') ?>

Hello <?php echo $name ?>!

La notación AcmeHelloBundle::layout.html.php ¿te suena familiar, no? Es la misma notación utilizada para referir una plantilla. La parte :: simplemente significa que el elemento controlador está vacío, por lo tanto el archivo correspondiente se almacena directamente bajo views/.

Ahora, echemos un vistazo al archivo layout.html.php:

<!-- src/Acme/HelloBundle/Resources/views/layout.html.php -->
<?php $view->extend('::base.html.php') ?>

<h1>Hello Application</h1>

<?php $view['slots']->output('_content') ?>

El diseño en sí mismo está decorado por otra (::base.html.php). Symfony2 admite varios niveles de decoración: un diseño en sí se puede decorar con otro. Cuando la parte nombre del paquete de la plantilla está vacía, se buscan las vistas en el directorio app/Resources/views/. Este directorio almacena vistas globales de tu proyecto completo:

<!-- app/Resources/views/base.html.php -->
<!DOCTYPE html>
    <html>
        <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title><?php $view['slots']->output('title', 'Hello Application') ?></title>
        </head>
        <body>
        <?php $view['slots']->output('_content') ?>
    </body>
</html>

Para ambos diseños, la expresión $view['slots']->output('_content') se sustituye por el contenido de la plantilla hija, index.html.php y layout.html.php, respectivamente (más de ranuras en la siguiente sección).

Como puedes ver, Symfony2 proporciona métodos en un misterioso objeto $view. En una plantilla, la variable $view siempre está disponible y se refiere a un objeto especial que proporciona una serie de métodos que hacen funcionar el motor de plantillas.

Trabajar con ranuras

Una ranura es un fragmento de código, definido en una plantilla, y reutilizable en cualquier diseño para decorar una plantilla. En la plantilla index.html.php, se define una ranura title:

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php -->
<?php $view->extend('AcmeHelloBundle::layout.html.php') ?>

<?php $view['slots']->set('title', 'Hello World Application') ?>

Hello <?php echo $name ?>!

El diseño base ya tiene el código para reproducir el título en el encabezado:

<!-- app/Resources/views/base.html.php -->
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title><?php $view['slots']->output('title', 'Hello Application') ?></title>
    </head>

El método output() inserta el contenido de una ranura y, opcionalmente, toma un valor predeterminado si la ranura no está definida. Y _content sólo es una ranura especial que contiene la plantilla hija reproducida.

Para ranuras grandes, también hay una sintaxis extendida:

<?php $view['slots']->start('title') ?>
    Una gran cantidad de HTML
<?php $view['slots']->stop() ?>

Incluyendo otras plantillas

La mejor manera de compartir un fragmento de código de plantilla es definir una plantilla que se pueda incluir en otras plantillas.

Crea una plantilla hello.html.php:

<!-- src/Acme/HelloBundle/Resources/views/Hello/hello.html.php -->
Hello <?php echo $name ?>!

Y cambia la plantilla index.html.php para incluirla:

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php -->
<?php $view->extend('AcmeHelloBundle::layout.html.php') ?>

<?php echo $view->render('AcmeHelloBundle:Hello:hello.html.php', array('name' => $name)) ?>

El método render() evalúa y devuelve el contenido de otra plantilla (este exactamente es el mismo método que utilizamos en el controlador).

Integrando otros controladores

¿Y si deseas incrustar el resultado de otro controlador en una plantilla? Eso es muy útil cuando se trabaja con Ajax, o cuando la plantilla incrustada necesita alguna variable que no está disponible en la plantilla principal.

Si creas una acción fancy, y quieres incluirla en la plantilla index.html.php, basta con utilizar el siguiente código:

<!-- src/Acme/HelloBundle/Resources/views/Hello/index.html.php -->
<?php echo $view['actions']->render('AcmeHelloBundle:Hello:fancy', array(
    'name'  => $name,
    'color' => 'green'
)) ?>

Aquí, la cadena AcmeHelloBundle:Hello:fancy se refiere a la acción fancy del controlador Hello:

// src/Acme/HelloBundle/Controller/HelloController.php

class HelloController extends Controller
{
    public function fancyAction($name, $color)
    {
        // crea algún objeto, basándose en la variable $color
        $object = ...;

        return $this->render('AcmeHelloBundle:Hello:fancy.html.php', array(
            'name'   => $name,
            'object' => $object
        ));
    }

    // ...
}

Pero ¿dónde se define el elemento arreglo $view['actions'] de la vista? Al igual que ``$view['slots'], este invoca a un ayudante de plantilla, y la siguiente sección contiene más información sobre ellos.

Usando ayudantes de plantilla

El sistema de plantillas de Symfony2 se puede extender fácilmente por medio de los ayudantes. Los ayudantes son objetos PHP que ofrecen funciones útiles en el contexto de la plantilla. actions y slots son dos de los ayudantes integrados en Symfony2.

Creando enlaces entre páginas

Hablando de aplicaciones web, forzosamente tienes que crear enlaces entre páginas. En lugar de codificar las URL en las plantillas, el ayudante router sabe cómo generar URL basándose en la configuración de enrutado. De esta manera, todas tus URL se pueden actualizar fácilmente cambiando la configuración:

<a href="<?php echo $view['router']->generate('hello', array('name' => 'Thomas')) ?>">
    Greet Thomas!
    </a>

El método generate() toma el nombre de la ruta y un arreglo de parámetros como argumentos. El nombre de la ruta es la clave principal en la cual son referidas las rutas y los parámetros son los valores de los marcadores de posición definidos en el patrón de la ruta:

# src/Acme/HelloBundle/Resources/config/routing.yml
hello: # El nombre de la ruta
    path:  /hello/{name}
    defaults: { _controller: AcmeHelloBundle:Hello:index }

Usando activos: imágenes, JavaScript y hojas de estilo

¿Qué sería de Internet sin imágenes, JavaScript y hojas de estilo? Symfony2 proporciona la etiqueta assets para hacer frente a los activos fácilmente:

<link href="<?php echo $view['assets']->getUrl('css/blog.css') ?>" rel="stylesheet" type="text/css" />

<img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" />

El principal objetivo del ayudante assets es hacer más portátil tu aplicación. Gracias a este ayudante, puedes mover el directorio raíz de tu aplicación a cualquier lugar bajo tu directorio raíz del servidor web sin cambiar nada en el código de tu plantilla.

Mecanismo de escape

Al utilizar plantillas PHP, escapa las variables cada vez que se muestren al usuario:

<?php echo $view->escape($var) ?>

De forma predeterminada, el método escape() supone que la variable se emite dentro de un contexto HTML. El segundo argumento te permite cambiar el contexto. Por ejemplo, para mostrar algo en un archivo de JavaScript, utiliza el contexto js:

<?php echo $view->escape($var, 'js') ?>
Bifúrcame en GitHub