Hola a tod@s. Te una duda con Twig. ¿Puedo crear información HTML a partir de una sola variable como se crean los formularios? Ejemplo: los formularios en Twig se generan con {{ form(form) }}
. ¿Podría crear una tabla? Ejemplo: {{ table(table) }}
.
¡Quedo atento!
Respuestas
En Twig tienes dos formas de hacerlo:
- Macros: si el contenido a generar se usa solamente en unas pocas plantillas.
- Funciones: si el contenido se genera por toda la aplicación.
Macros
Consulta la documentación oficial sobre macros de Twig y verás que es tan sencillo como hacer lo siguiente:
{% macro table(parameters) %} <table> ... </table> {% endmacro %}
Y en la plantilla donde quieras usar este macro, copias su contenido y haces lo siguiente:
{% import _self as html %} {{ html.table(items) }}
También puedes guardar las macros en una plantilla Twig específica e importarla en todas las demás plantillas que vayan a usar esas macros.
Funciones
Consulta la documentación oficial sobre cómo crear una extensión Twig en Symfony y cómo extender Twig mediante funciones:
Primero crea una clase para definir una extensión de Twig:
// src/AppBundle/Twig/AppExtension.php namespace AppBundle\Twig; class AppExtension extends \Twig_Extension { public function getFunctions() { return array( new \Twig_SimpleFunction('table', array($this, 'createTable'), array('is_safe' => array('html'))), ); } public function createTable($parameters) { $html = '<table>'; // ... $html .= '</table>'; return $html; } public function getName() { return 'app_extension'; } }
Después define un servicio para que esta extensión se active en toda la aplicación:
# app/config/services.yml services: app.twig_extension: class: AppBundle\Twig\AppExtension public: false tags: - { name: twig.extension }
Y ya está. Ahora ya puedes incluir lo siguiente en cualquier plantilla de la aplicación:
{{ table(items) }}
Lo único que debes tener en cuenta es que al definir la función con Twig_SimpleFunction()
es muy importante que en el tercer argumento incluyas lo siguiente: array('is_safe' => array('html'))
. Esto le dice a Twig que tu función está generando contenido HTML y por tanto, que no debe escaparlo sino mostrarlo directamente en el navegador.
@javiereguiluz
¡Muchas gracias buen hombre!
@cristian_angulo
Hola. Les comparto. En ocasiones necesitamos pasarle parámetros a nuestra plantilla en la extensión que estamos creando y renderizar. Se hace de esta manera:
namespace AppBundle\Twig; class AppExtension extends \Twig_Extension { public function getFunctions() { return array( new \Twig_SimpleFunction('table', array($this, 'createTable'), array('is_safe' => array('html'), 'needs_environment' => true )), ); } public function createTable(\Twig_Environment $twig = null, $parameters) { return $twig->render('AppBundle::table.html.twig', array('parameters' => $parameters)); } public function getName() { return 'app_extension'; } }
Donde vamos a mostrar la información llamamos nuestra extensión: {{ table('tabla') }}
Acá, información para complementar: Rendering templates from a Twig extension
@cristian_angulo
@cristian_angulo, muchas gracias por mostrar la solución final que habéis utilizado. Efectivamente tienes razón y en este caso era mejor usar el environment de Twig para renderizar la plantilla Twig en vez de generar el código HTML a mano.
@javiereguiluz
Buenas, para este caso específico donde tu extensión solo va a renderizar un template sin hacer nada más, puedes simplemente desde cualquier archivo .twig usar la función include
:
{{ include("AppBundle::table.html.twig", { ... }) }}
Esta acotación es para que otras personas no vayan a crear extensiones solo para renderizar plantillas.
Saludos!
@manuel_j555