Login to bookmark this video
Buy Access to Course
19.

Unir a través de una relación de muchos a muchos

|

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

¿Te has preguntado alguna vez en qué nave de la flota hay más droides? Yo también Hagamos una lista de todas las naves en orden ascendente según su número de droides.

Sumérgete en src/Controller/MainController.php. La consulta es:$ships = $repository->findIncomplete();.

Haz clic en ese método y dale un nombre nuevo y elegante:findIncompleteOrderedByDroidCount():

67 lines | src/Repository/StarshipRepository.php
// ... lines 1 - 14
class StarshipRepository extends ServiceEntityRepository
{
// ... lines 17 - 24
public function findIncompleteOrderedByDroidCount(): Pagerfanta
{
// ... lines 27 - 34
}
// ... lines 36 - 65
}

Cópialo, vuelve al controlador y sustituye el método antiguo por el nuevo:

30 lines | src/Controller/MainController.php
// ... lines 1 - 10
class MainController extends AbstractController
{
#[Route('/', name: 'app_homepage')]
public function homepage(
// ... lines 15 - 16
): Response {
$ships = $repository->findIncompleteOrderedByDroidCount();
// ... lines 19 - 27
}
}

Aún no hemos cambiado nada, así que una actualización rápida nos da lo mismo.

Para ordenar las naves estelares por su número de droides, tenemos que unir la tabla de unión hasta droid, agrupar porstarship, y luego contar los droides. Guau. En realidad, ¡es bastante bonito!

En StarshipRepository, añade un leftJoin(). Pero no vamos a pensar en la tabla de unión ni en la base de datos. No, céntrate sólo en las relaciones en Doctrine. Así que estamos uniendo a través de s, que es nuestra nave estelar, y droids, la propiedad que tiene la relación ManyToMany con Droid. Por último, aliasamos esos droides como droid.

Para contar los droides, añade un groupBy('s.id').

Para ordenar sustituye el orderBy() existente por orderBy('COUNT(droid)', 'ASC'):

69 lines | src/Repository/StarshipRepository.php
// ... lines 1 - 14
class StarshipRepository extends ServiceEntityRepository
{
// ... lines 17 - 24
public function findIncompleteOrderedByDroidCount(): Pagerfanta
{
$query = $this->createQueryBuilder('s')
// ... line 28
->orderBy('COUNT(droid)', 'ASC')
->leftJoin('s.droids', 'droid')
->groupBy('s.id')
// ... lines 32 - 33
;
// ... lines 35 - 36
}
// ... lines 38 - 67
}

Después, pulsa actualizar y ¡boom! En la parte superior, verás droids none. Pero a medida que te desplazas hacia abajo, el recuento de droides aumenta. Si eres lo suficientemente valiente como para aventurarte unas páginas más adelante, ¡empezaremos a ver naves estelares con dos, tres o incluso cuatro droides!

¿La clave? No hay nada especial en esta unión. Nos unimos a través de la propiedad y Doctrine se encarga del resto.

Si echas un vistazo a la consulta en esta página, verás que se encarga de todos los detalles. Busca starship_droid para encontrar la consulta. Esto es feo, pero si formateas la consulta, selecciona de starship, encargándose de la unión a la tabla de unión y uniéndose de nuevo a droid. Eso nos permite contar y ordenar por ese recuento en esa tabla droid. ¡Impresionante Doctrine, impresionante!

¡Eso es técnicamente todo para ManyToMany! Pero a continuación vamos a tratar un caso de uso más avanzado, pero aún común: añadir datos a la tabla join, como la fecha en que el droide se unió a la nave estelar.