Consulta de la base de datos
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeAhora que hemos guardado algunas cosas en la base de datos, ¿cómo podemos leerlas o consultarlas? Una vez más, al menos para las cosas sencillas, Doctrine no quiere que te preocupes de consultarlas. En lugar de eso, simplemente pedimos a Doctrine los objetos que queremos.
Dirígete a src/Controller/VinylController.php
y busca la acción browse()
.
// ... lines 1 - 10 | |
class VinylController extends AbstractController | |
{ | |
// ... lines 13 - 37 | |
public function browse(string $slug = null): Response | |
{ | |
$genre = $slug ? u(str_replace('-', ' ', $slug))->title(true) : null; | |
$mixes = $this->mixRepository->findAll(); | |
return $this->render('vinyl/browse.html.twig', [ | |
'genre' => $genre, | |
'mixes' => $mixes, | |
]); | |
} | |
} |
Aquí, estamos cargando todo el $mixes
en nuestro proyecto... y actualmente lo estamos haciendo a través de esta clase de servicio MixRepository
que creamos en el último episodio. Esta clase habla con un repositorio de GitHub y lee desde un archivo de texto codificado.
Vamos a dejar de usar este MixRepository
y en su lugar cargaremos estos $mixes
desde la base de datos.
Consulta a través del Gestor de Entidades
Bien: para guardar los objetos, aprovechamos el servicio EntityManagerInterface
, que es el más importante con diferencia en Doctrine. Además, este servicio puede consultar los objetos. Aprovechemos eso. Añade un nuevo argumento a browse()
, de tipo EntityManagerInterface
... y llámalo $entityManager
.
// ... lines 1 - 6 | |
use Doctrine\ORM\EntityManagerInterface; | |
// ... lines 8 - 12 | |
class VinylController extends AbstractController | |
{ | |
// ... lines 15 - 39 | |
public function browse(EntityManagerInterface $entityManager, string $slug = null): Response | |
{ | |
// ... lines 42 - 51 | |
} | |
} |
A continuación, sustituye la línea $mixes
por dos líneas. Empieza con$mixRepository = $entityManager->getRepository()
pasándole el nombre de la clase desde la que queremos consultar. Sí, pensamos en consultar desde una clase de entidad, no desde una tabla. En este caso, queremos consultar desde VinylMix::class
.
Hablaremos más sobre este concepto de repositorio en un minuto. A continuación, para obtener las mezclas en sí, digamos $mixes = $mixRepository->
y llamemos a uno de los métodos de la misma: findAll()
.
Para ver qué nos da esto, vamos a dd($mixes)
.
// ... lines 1 - 39 | |
public function browse(EntityManagerInterface $entityManager, string $slug = null): Response | |
{ | |
// ... lines 42 - 43 | |
$mixRepository = $entityManager->getRepository(VinylMix::class); | |
$mixes = $mixRepository->findAll(); | |
dd($mixes); | |
// ... lines 47 - 51 | |
} | |
// ... lines 53 - 54 |
Bien, ¡es hora de probar! Gira, vuelve a la página de inicio, haz clic en "Examinar las mezclas" para realizar esa acción, y... ¡voilá! ¡Obtenemos seis resultados! Y cada uno de ellos, lo más importante, es un objeto VinylMix
.
Entre bastidores, Doctrine consultó la tabla y las columnas. Pero en lugar de darnos esos datos en bruto, los puso en objetos y nos los dio, lo cual es mucho más agradable.
Trabajar con objetos en Twig
Si eliminamos el dd()
... este array de objetos VinylMix
se pasará a la plantilla, en lugar del array de datos que teníamos antes. Pero... la página sigue funcionando. Sin embargo, estas imágenes están rotas porque, al parecer, el servicio que estoy utilizando para cargarlas no funciona en este momento. Ah... las alegrías de la grabación de vídeo. ¡Pero eso no nos detendrá!
El hecho de que todos los datos se sigan renderizando sin errores es... en realidad un poco por suerte. Cuando renderizamos la plantilla - templates/vinyl/browse.html.twig
- hacemos un bucle sobre todos los mixes
. La plantilla funciona porque el antiguo archivo de texto del repositorio de GitHub tenía las mismas claves (como title
, trackCount
y genre
) que nuestra claseVinylMix
.
// ... lines 1 - 28 | |
{% for mix in mixes %} | |
// ... line 30 | |
<div class="mixed-vinyl-container p-3 text-center"> | |
// ... line 32 | |
<p class="mt-2"><strong>{{ mix.title }}</strong></p> | |
<span>{{ mix.trackCount }} Tracks</span> | |
| | |
<span>{{ mix.genre }}</span> | |
| | |
<span>{{ mix.createdAt|ago }}</span> | |
// ... lines 39 - 40 | |
{% endfor %} | |
// ... lines 42 - 46 |
Sin embargo, aquí ocurre algo interesante. Cuando decimos mix.genre
,mix
es ahora un objeto... y esta propiedad genre
es privada. Eso significa que no podemos acceder a ella directamente. Pero Twig es inteligente. Se da cuenta de que es privada y busca un método getGenre()
. Así que en nuestra plantilla, decimos mix.genre
, pero en realidad, llama al método getGenre()
. Eso es bastante asombroso.
Visualización de las consultas de la página
¿Sabes qué más es impresionante? ¡Podemos ver las consultas que hace cualquier página! En la barra de herramientas de depuración de la web, Doctrine nos ofrece un nuevo y elegante icono. Oooo. Y si hacemos clic en él... ¡tah dah! Hay una consulta a la base de datos... e incluso podemos ver de qué se trata. También se puede ver una versión formateada de la misma... aunque tengo que actualizar la página para que esto funcione... porque la biblioteca Turbo JavaScript que instalamos en el primer tutorial no siempre se lleva bien con esta zona del perfilador. De todos modos, también podemos ver una versión ejecutable de la consulta o ejecutar "Explicar" sobre ella.
El "Repositorio"
Muy bien, de vuelta al controlador, aunque podemos consultar a través deEntityManagerInterface
, normalmente consultamos a través de algo llamado repositorio.dd()
este objeto $mixRepository
para obtener más información sobre él
// ... lines 1 - 12 | |
class VinylController extends AbstractController | |
{ | |
// ... lines 15 - 39 | |
public function browse(EntityManagerInterface $entityManager, string $slug = null): Response | |
{ | |
// ... lines 42 - 44 | |
dd($mixRepository); | |
// ... lines 46 - 51 | |
} | |
} |
Luego vuelve a la página /browse
y... es un objetoApp\Repository\VinylMixRepository
. Oye, ¡conocemos esa clase! Vive en nuestro código, en el directorio src/Repository/
. Fue generada por MakerBundle.
Dentro del atributo ORM\Entity
sobre nuestra clase de entidad, MakerBundle generó una opción repositoryClass
que apunta a esto. Gracias a esta configuración, nuestra entidad, VinylMix
, está vinculada a VinylMixRepository
. Así que cuando le pides a Doctrine que nos dé el repositorio de la clase VinylMix
, sabe que debe devolver el objetoVinylMixRepository
.
El repositorio de una entidad lo sabe todo sobre cómo consultar sus datos. Y, sin que nosotros hagamos nada, ya tiene un montón de métodos útiles para las consultas básicas, como findAll()
, findOneBy()
y varios más. Dentro de un rato, aprenderemos a añadir nuevos métodos al repositorio para realizar consultas personalizadas.
De todos modos, VinylMixRepository
es en realidad un servicio en el contenedor... así que podemos obtenerlo más fácilmente autoconectándolo directamente. Añade un argumentoVinylMixRepository $mixRepository
... y entonces no necesitaremos esta línea. Esto es más sencillo... ¡y sigue funcionando!
// ... lines 1 - 38 | |
public function browse(VinylMixRepository $mixRepository, string $slug = null): Response | |
{ | |
// ... lines 41 - 42 | |
$mixes = $mixRepository->findAll(); | |
// ... lines 44 - 48 | |
} | |
// ... lines 50 - 51 |
La conclusión es ésta: si quieres consultar una tabla, lo harás a través del repositorio de la entidad cuyos datos necesitas.
Siguiente: El hecho de que hayamos cambiado nuestro código para cargarlo desde la base de datos y no hayamos tenido que actualizar nuestra plantilla Twig en absoluto fue algo impresionante Y por cortesía de un poco de magia Twig. Vamos a hablar más de esa magia y a crear una propiedad virtual que podemos imprimir en la plantilla.
Received following error: Cannot autowire service "App\Controller\VinylController": argument "$isDebug" of method "__construct()" is type-hinted "bool", you should configure its value explicitly. The Solution: I had to define another service in the services.yaml, on the last rows, after the Mixrepository Service: