This course is still being released! Check back later for more chapters.

Get Notified About this Course!

We will send you messages regarding this course only
and nothing else, we promise.
You can unsubscribe anytime by emailing us at:
privacy@symfonycasts.com
Login to bookmark this video
Buy Access to Course
06.

Herencia con Twig

|

Share this awesome video!

|

Keep on Learning!

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

¿Ves cada una de estas filas de naves estelares de aquí? Muestran las propiedades genéricas de la nave estelar. Quiero hacerlas un poco más interesantes mostrando en estas filas las propiedades personalizadas de las naves estelares para nuestras subnavegaciones. Llamemos a esta fila "teaser".

Crear una Parcial Teaser

Lo primero que haremos será extraer el HTML de nuestro teaser en un parcial.

En nuestro directorio templates, crea un nuevo directorio starshipy, a continuación, crea un archivo Twig llamado teaser.html.twig.

Luego, en la plantilla de nuestra página de inicio, busca el HTML del teaser, que es todo lo que hay dentro de esta sección "for ship in ships". Coge todo ese trozo y córtalo. A continuación, pégalo en nuestro nuevo archivo teaser.html.twig:

<div class="bg-[#16202A] rounded-2xl pl-5 py-5 pr-11 flex flex-col min-[1174px]:flex-row min-[1174px]:justify-between">
<div class="flex justify-center min-[1174px]:justify-start">
<img class="h-[83px] w-[84px]" src="{{ asset(ship.statusImageFilename) }}" alt="Status: {{ ship.statusString }}">
<div class="ml-5">
<div class="rounded-2xl py-1 px-3 flex justify-center w-32 items-center bg-amber-400/10">
<div class="rounded-full h-2 w-2 bg-amber-400 blur-[1px] mr-2"></div>
<p class="uppercase text-xs text-nowrap">{{ ship.statusString }}</p>
</div>
<h4 class="text-[22px] pt-1 font-semibold">
<a
class="hover:text-slate-200"
href="#"
>
{{ ship.type|replace({'_': ' '})|title }}
{{ ship.name }}
</a>
</h4>
<div>
Arrived at: {{ ship.arrivedAt|ago }}
</div>
</div>
</div>
<div class="flex justify-center min-[1174px]:justify-start mt-2 min-[1174px]:mt-0 shrink-0">
<div class="border-r border-white/20 pr-8">
<p class="text-slate-400 text-xs text-right">Captain</p>
<p class="text-xl">{{ ship.captain }}</p>
</div>
<div class="pl-8 w-[100px]">
<p class="text-slate-400 text-xs">Class</p>
<p class="text-xl">{{ ship.class }}</p>
</div>
</div>
</div>

De vuelta en homepage.html.twig, inclúyelo como parcial con:{{ include('starship/teaser.html.twig') }}. Para los parámetros, pasa{ship: ship}:

22 lines | templates/main/homepage.html.twig
// ... lines 1 - 4
{% block body %}
<main class="flex flex-col lg:flex-row">
// ... lines 7 - 8
<div class="px-12 pt-10 w-full">
// ... lines 10 - 13
<div class="space-y-5">
{% for ship in ships %}
{{ include('starship/teaser.html.twig', {ship: ship}) }}
{% endfor %}
</div>
</div>
</main>
{% endblock %}

Realiza una comprobación rápida actualizando la aplicación para ver si todo sigue en orden. Perfecto. ¡Sin regresiones!

Añadir propiedades al teaser

Ahora que tenemos el teaser en su propio parcial, vamos a animarlo con propiedades de los subbuques. Por ejemplo, quiero mostrar la capacidad de carga de los cargueros. Podríamos hacerlo con una sentencia if... como if ship.type == 'freighter', pero eso se complicaría muy rápido. En su lugar, utilicemos la herencia de plantillas Twig. Herencia de plantillas Twig con herencia Doctrine, ¡me encanta!

Primero, en el directorio templates/starship, crea un nuevo directorio teaser. Éste será el hogar de todas nuestras plantillas teaser heredadas. Crea la primera, freighter.html.twig.

De vuelta en teaser.html.twig, necesitamos crear un bloque que pueda ser anulado por nuestras plantillas heredadas. Debajo del "llegado a", añade {% block extra %}{% endblock %}:

36 lines | templates/starship/teaser.html.twig
<div class="bg-[#16202A] rounded-2xl pl-5 py-5 pr-11 flex flex-col min-[1174px]:flex-row min-[1174px]:justify-between">
<div class="flex justify-center min-[1174px]:justify-start">
// ... line 3
<div class="ml-5">
// ... lines 5 - 17
<div>
Arrived at: {{ ship.arrivedAt|ago }}
</div>
{% block extra %}{% endblock %}
</div>
</div>
// ... lines 24 - 34
</div>

Esto está vacío en la plantilla teaser genérica, pero va a permitir que las plantillas que la extiendan, lo anulen.

Salta a nuestra nueva plantilla freighter. Ups, tengo un error tipográfico en el nombre del archivo. Debería ser.twig con un i.

Primero, haz que amplíe starship/teaser.html.twig. Ahora, anula el bloque extra y, dentro, añade <div>Cargo Capacity: {{ ship.cargoCapacity }}</div>. Podríamos llamar aquí a parent() para mostrar el bloque padre, pero como está vacío, me lo saltaré por ahora:

{% extends 'starship/teaser.html.twig' %}
{% block extra %}
<div>Cargo Capacity: {{ ship.cargoCapacity }}</div>
{% endblock %}

Herencia dinámica de plantillas

¿Listo para ver algo de magia? En nuestra plantilla de página de inicio, incluiremos dinámicamente la plantilla teaser correcta en función del tipo de nave. Dentro de include(), rompe la cadena después de teaser y añade algunos ~'s para concatenar. Dentro de ellos, añade ship.type:

22 lines | templates/main/homepage.html.twig
// ... lines 1 - 4
{% block body %}
<main class="flex flex-col lg:flex-row">
// ... lines 7 - 8
<div class="px-12 pt-10 w-full">
// ... lines 10 - 13
<div class="space-y-5">
{% for ship in ships %}
{{ include('starship/teaser/'~ship.type~'.html.twig', {ship: ship}) }}
{% endfor %}
</div>
</div>
</main>
{% endblock %}

De vuelta en nuestra aplicación, actualiza y... ¡error! "No se puede encontrar la plantilla starship/teaserfreighter.html.twig". Uy, se me ha olvidado un / después de teaser. Lo arreglo y actualizo de nuevo...

Sigue habiendo un error, ¡pero diferente! "No se puede encontrar la plantilla starship/teaser/scout.html.twig". Ahh, sólo hemos creado un teaser para el freighter, pero también tenemos un scout y un mining_freighter.

Para que esto funcione, tenemos que crear un teaser para cada tipo de nave. Pero, ¿y si no quiero tener ese requisito? Me gustaría simplemente recurrir al teaser genérico si no existe uno específico. ¡No hay problema!

Teaser alternativo

En homepage.html.twig, envuelve el nombre de la plantilla en la función include() en una matriz. Cuando pases una matriz a include(), Twig intentará encontrar cada plantilla en la matriz. Utilizará la primera que encuentre. Así, para el segundo elemento de la matriz, utiliza nuestro teaser genérico: starship/teaser.html.twig:

22 lines | templates/main/homepage.html.twig
// ... lines 1 - 4
{% block body %}
<main class="flex flex-col lg:flex-row">
// ... lines 7 - 8
<div class="px-12 pt-10 w-full">
// ... lines 10 - 13
<div class="space-y-5">
{% for ship in ships %}
{{ include(['starship/teaser/'~ship.type~'.html.twig', 'starship/teaser.html.twig'], {ship: ship}) }}
{% endfor %}
</div>
</div>
</main>
{% endblock %}

Actualiza nuestra aplicación... ¡y ya está! ¡Nuestros cargueros muestran ahora su capacidad de carga! Y a continuación, los exploradores y los cargueros mineros utilizan el teaser genérico.

Añadir una plantilla de carguero minero

Pasemos a otro nivel y añadamos un teaser para el mining_freighter.

En templates/starship/teaser, crea un nuevo archivo Twig: mining_freighter.html.twig. Al igual que nuestra entidad MiningFreighter extiende Freighter, esta plantilla extenderá el teaser freighter.html.twig.

Añade el bloque extra. Esta vez, renderiza el bloque parent() para incluir la capacidad de carga del teaser freighter. A continuación, añade <div>Laser Power: {{ ship.laserPower }}</div>:

{% extends 'starship/teaser/freighter.html.twig' %}
{% block extra %}
{{ parent() }}
<div>Laser Power: {{ ship.laserPower }}</div>
{% endblock %}

Gracias a nuestra lógica de herencia dinámica de plantillas, esto es todo lo que deberíamos hacer. Actualiza la aplicación... desplázate hasta nuestros cargueros mineros... ¡y genial, muestran tanto la capacidad de carga como la potencia láser!

Creo que esto es bastante elegante, ¿y tú?

A continuación veremos cómo funcionan conjuntamente la Herencia de Doctrine y las rutas