embed

La etiqueta embed combina el comportamiento de include y extends. Te permite incluir el contenido de otra plantilla, al igual que include. Pero también te permite anular cualquier bloque definido dentro de la plantilla incluida, como cuando extiendes una plantilla.

Piensa en una plantilla incrustada como un "micro esqueleto de diseño".

{% embed "teasers_skeleton.html.twig" %}
    {# Estos bloques están definidos en "teasers_skeleton.html.twig" #}
    {# y los anulamos aquí mismo: #}
    {% block left_teaser %}
        Some content for the left teaser box
    {% endblock %}
    {% block right_teaser %}
        Some content for the right teaser box
    {% endblock %}
{% endembed %}

La etiqueta embed lleva la idea de la herencia de plantillas al nivel de fragmentos de contenido. Mientras que la herencia de plantillas permite "esqueletos de documentos" que son llenados de vida por las plantillas hijas, la etiqueta embed te permite crear "esqueletos" para unidades más pequeñas de contenido y reutilizarlos y llenarlos donde quieras.

Dado que el caso de uso puede no ser obvio, veamos un ejemplo simplificado. Imagina una plantilla base compartida por múltiples páginas HTML, que define un solo bloque llamado "content":

┌─── page layout ─────────────────────┐
│                                     │
│           ┌── block "content" ──┐   │
│           │                     │   │
│           │                     │   │
│           │ (child template to  │   │
│           │  put content here)  │   │
│           │                     │   │
│           │                     │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

Algunas páginas ("page_1" y "page_2") comparten la misma estructura de contenido: dos cajas apiladas verticalmente:

┌─── page layout ─────────────────────┐
│                                     │
│           ┌── block "content" ──┐   │
│           │ ┌─ block "top" ───┐ │   │
│           │ │                 │ │   │
│           │ └─────────────────┘ │   │
│           │ ┌─ block "bottom" ┐ │   │
│           │ │                 │ │   │
│           │ └─────────────────┘ │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

Mientras que otras páginas ("page_3" y "page_4") comparten una estructura de contenido diferente: dos cajas lado a lado:

┌─── page layout ─────────────────────┐
│                                     │
│           ┌── block "content" ──┐   │
│           │                     │   │    
│           │ ┌ block ┐ ┌ block ┐ │   │
│           │ │"left" │ │"right"│ │   │
│           │ │       │ │       │ │   │
│           │ │       │ │       │ │   │
│           │ └───────┘ └───────┘ │   │
│           └─────────────────────┘   │
│                                     │
└─────────────────────────────────────┘

Sin la etiqueta embed, tienes dos formas de diseñar tus plantillas:

  • Crear dos plantillas base "intermedias" que extiendan la plantilla de diseño maestra: una con cajas apiladas verticalmente para ser usada por las páginas "page_1" y "page_2" y otra con cajas lado a lado para las páginas "page_3" y "page_4".
  • Incrustar el marcado para las cajas superior/inferior e izquierda/derecha directamente en cada plantilla de página.

Estas dos soluciones no escalan bien porque cada una tiene un inconveniente importante:

  • La primera solución puede funcionar para este ejemplo simplificado. Pero imagina que agregamos una barra lateral, que puede contener nuevamente diferentes estructuras recurrentes de contenido. Ahora necesitaríamos crear plantillas base intermedias para todas las combinaciones que ocurran de estructura de contenido y estructura de barra lateral... y así sucesivamente.
  • La segunda solución implica la duplicación de código común con todas sus consecuencias negativas: cualquier cambio implica encontrar y editar todas las copias afectadas de la estructura, la corrección debe verificarse para cada copia, las copias pueden desincronizarse por modificaciones descuidadas, etc.

En tal situación, la etiqueta embed es muy útil. El código de diseño común puede vivir en una sola plantilla base, y las dos estructuras de contenido diferentes, llamémoslas "micro diseños", van a plantillas separadas que se incrustan según sea necesario:

Plantilla de página page_1.html.twig:

{% extends "layout_skeleton.html.twig" %}

{% block content %}
    {% embed "vertical_boxes_skeleton.html.twig" %}
        {% block top %}
            Some content for the top box
        {% endblock %}

        {% block bottom %}
            Some content for the bottom box
        {% endblock %}
    {% endembed %}
{% endblock %}

Y aquí está el código para vertical_boxes_skeleton.html.twig:

<div class="top_box">
    {% block top %}
        Top box default content
    {% endblock %}
</div>

<div class="bottom_box">
    {% block bottom %}
        Bottom box default content
    {% endblock %}
</div>

El objetivo de la plantilla vertical_boxes_skeleton.html.twig es factorizar el marcado HTML para las cajas.

La etiqueta embed toma exactamente los mismos argumentos que la etiqueta include:

{% embed "base" with {'name': 'Fabien'} %}
    ...
{% endembed %}

{% embed "base" with {'name': 'Fabien'} only %}
    ...
{% endembed %}

{% embed "base" ignore missing %}
    ...
{% endembed %}

Warning

Como las plantillas incrustadas no tienen "nombres", las estrategias de auto-escape basadas en el nombre de la plantilla no funcionarán como se espera si cambias el contexto (por ejemplo, si incrustas una plantilla CSS/JavaScript en una HTML). En ese caso, establece explícitamente la estrategia de auto-escape predeterminada con la etiqueta autoescape.

Note

Ver también: include