Login to bookmark this video
Buy Access to Course
07.

Enrutamiento con la herencia de Doctrine

|

Share this awesome video!

|

Lucky you! You found an early release chapter - it will be fully polished and published shortly!

This Chapter isn't quite ready...

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

Vamos a crear una página de demostración dedicada para nuestras naves estelares y a comprobar cómo funciona el enrutamiento con las entidades de herencia Doctrine. Primero necesitamos un nuevo controlador, así que espera al terminal y ejecuta:

symfony console make:controller Starship

No es necesario realizar ninguna prueba. Bien, salta a tu IDE y busca nuestro nuevo y brillanteStarshipController. Empieza por cambiar el nombre del método a show(). A continuación, en el atributo#[Route], cambia la ruta a /starship/{id}, y nómbralo app_starship_show:

Por último, vamos a utilizar la magia del resolvedor de valores de entidad de Doctrine para inyectar el Starship para el id pasado. Añade Starship $ship como argumento al método show():

22 lines | src/Controller/StarshipController.php
// ... lines 1 - 9
final class StarshipController extends AbstractController
{
#[Route('/starship/{id}', name: 'app_starship_show')]
public function index(Starship $ship): Response
// ... lines 14 - 20
}

Por ahora, sólo dd($ship) para verlo en acción:

22 lines | src/Controller/StarshipController.php
// ... lines 1 - 9
final class StarshipController extends AbstractController
{
// ... line 12
public function index(Starship $ship): Response
{
dd($ship);
// ... lines 16 - 19
}
}

Enlace a la página Mostrar

Ahora, dirígete a nuestra plantilla teaser genérica. Busca el enlace del marcador de posición (el que tiene # como href). Sustitúyelo por {{ path('app_starship_show') }} y{id: ship.id} como parámetros:

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 - 8
<h4 class="text-[22px] pt-1 font-semibold">
<a
// ... line 11
href="{{ path('app_starship_show', {id: ship.id}) }}"
>
// ... lines 14 - 15
</a>
</h4>
// ... lines 18 - 21
</div>
</div>
// ... lines 24 - 34
</div>

Actualiza nuestra página de inicio y haz clic en el primer carguero. Este volcado nos muestra esta instanciaFreighter. Vuelve a la página de inicio y haz clic en el último carguero minero. Ahora el volcado nos muestra una instancia MiningFreighter. Aunque hemos indicadoStarship, Doctrine sabe que debe instanciar la clase de entidad correcta.

Si todo esto funciona exactamente como esperabas, tienes razón, realmente no hay nada especial en el enrutamiento y la herencia Doctrine.

Comprender la sugerencia de tipos

Pero toma nota: si vuelves a StarshipController::show(), y cambias la sugerencia de tipo de Starship a Scout:

23 lines | src/Controller/StarshipController.php
// ... lines 1 - 10
final class StarshipController extends AbstractController
{
// ... line 13
public function index(Scout $ship): Response
// ... lines 15 - 21
}

Acabarás con un error 404 cuando actualices la página. ¿Por qué? Porque no hay ninguna nave exploradora con este ID. Así que, para asegurarte de que se puede encontrar cualquier nave en esta ruta, tu sugerencia de tipo debe ser Starship, la entidad más alta que quieras encontrar para esta ruta:

22 lines | src/Controller/StarshipController.php
// ... lines 1 - 9
final class StarshipController extends AbstractController
{
// ... line 12
public function index(Starship $ship): Response
// ... lines 14 - 20
}

Preparar la plantilla de presentación

Preparemos la plantilla de este controlador. El bundle creador creó este archivoindex.html.twig en nuestro directorio templates/starship. Cámbiale el nombre a show.html.twig. Ábrelo y sustituye el bloque de título por {{ ship.name }}:

42 lines | templates/starship/show.html.twig
// ... lines 1 - 2
{% block title %}{{ ship.name }}{% endblock %}
// ... lines 4 - 42

Elimina todo el texto repetitivo del bloque body.

Para simplificar, copia el contenido de nuestra plantilla teaser y pégalo en el bloque body de la plantilla show.

42 lines | templates/starship/show.html.twig
// ... lines 1 - 4
{% block body %}
<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="{{ path('app_starship_show', {id: ship.id}) }}"
>
{{ ship.type|replace({'_': ' '})|title }}
{{ ship.name }}
</a>
</h4>
<div>
Arrived at: {{ ship.arrivedAt|ago }}
</div>
{% block extra %}{% endblock %}
</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>
{% endblock %}

En una aplicación del mundo real, la plantilla de espectáculo probablemente sería bastante diferente, ofreciendo más detalles y un diseño distinto.

Vuelve a StarshipController::show(), elimina el dd(), cambia la plantilla astarship/show.html.twig, y pasa ship como parámetro.

20 lines | src/Controller/StarshipController.php
// ... lines 1 - 9
final class StarshipController extends AbstractController
{
// ... line 12
public function index(Starship $ship): Response
{
return $this->render('starship/show.html.twig', [
'ship' => $ship,
]);
}
}

Ahora, vuelve a nuestra aplicación y actualiza la página. Por supuesto, esto parece el teaser, pero en realidad se trata de nuestra página de presentación independiente.

Implementar la herencia de plantillas Twig

Al igual que hicimos con los teasers, podemos utilizar la herencia de plantillas Twig con nuestra plantilla de espectáculo. Sin embargo, esto requiere un enfoque diferente, ya que estamos renderizando la plantilla dentro de un controlador, no con la función include() en otra plantilla Twig.

En primer lugar, copia el directorio teaser en show dentro del directorio templates/starship. Éstas serán las plantillas de espectáculo personalizadas y específicas de la entidad. Abre show/freighter.html.twig, y cambia el extends por starship/show.html.twig:

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

En show/mining_freighter.html.twig, cambia el extends por starship/show/freighter.html.twig:

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

Ya estamos listos para utilizar estas plantillas, pero tenemos que averiguar cuál renderizar.

Al principio, podrías pensar que podrías hacer lo mismo con render() y simplemente cambiarla por una matriz. Pero render() es estrictamente de tipo cadena para la vista. Así que... tenemos que ensuciarnos un poco las manos.

En StarshipController::show(), vamos a darnos un respiro e inyectar el servicio de entorno Twig con Environment, el del espacio de nombres Twig, $twig:

29 lines | src/Controller/StarshipController.php
// ... lines 1 - 10
final class StarshipController extends AbstractController
// ... lines 12 - 13
public function index(
// ... line 15
Environment $twig,
): Response {
// ... lines 18 - 26
}
}

A continuación, crea una variable $template. Para ello, utilizaremos la interpolación de cadenas para construir el nombre de la plantilla: starship/show/{$ship->getType()}.html.twig.

29 lines | src/Controller/StarshipController.php
// ... lines 1 - 10
final class StarshipController extends AbstractController
// ... lines 12 - 13
public function index(
// ... lines 15 - 16
): Response {
$template = "starship/show/{$ship->getType()}.html.twig";
// ... lines 19 - 26
}
}

Este es el nombre de la plantilla para el tipo específico de nave.

Si esta plantilla no existe, queremos recurrir a la plantilla genérica del programa.

Así que, if (!$twig->getLoader()->exists($template)), y dentro, pon $template a starship/show.html.twig:

29 lines | src/Controller/StarshipController.php
// ... lines 1 - 10
final class StarshipController extends AbstractController
// ... lines 12 - 13
public function index(
// ... lines 15 - 16
): Response {
// ... lines 18 - 19
if (!$twig->getLoader()->exists($template)) {
$template = 'starship/show.html.twig';
}
// ... lines 23 - 26
}
}

Por último, sustituye la cadena del método render() por nuestra nueva variable $template:

29 lines | src/Controller/StarshipController.php
// ... lines 1 - 10
final class StarshipController extends AbstractController
// ... lines 12 - 13
public function index(
// ... lines 15 - 16
): Response {
// ... lines 18 - 23
return $this->render($template, [
'ship' => $ship,
]);
}
}

Esto es muy similar a lo que la función include() de Twig hace por nosotros cuando pasas una matriz.

Salta a nuestra aplicación y actualiza... Genial, como se trata de un carguero minero, ahora vemos la capacidad de carga y la potencia láser. Ve a la página de inicio y haz clic en el primer carguero normal. Genial, ahora vemos la capacidad de carga.

Puedes pasar el ratón por encima del icono Twig de la barra de herramientas de depuración web para ver la plantilla utilizada. Efectivamente,starship/show/freighter.html.twig.

Vuelve a la página de inicio y haz clic en un explorador. Genial, no hay detalles adicionales, y la barra de herramientas muestra que se está renderizando la plantilla genérica starship/show.html.twig.

¡Nuestro sistema casero de plantillas dinámicas funciona!

A continuación veremos cómo funcionan las asociaciones con la Herencia de Doctrine y qué consideraciones debes tener en cuenta al utilizarlas.