Nasze pierwsze spotkanie z Query Builderem Symfony, który wygląda zupełnie inaczej niż Eloquent ORM Laravela. Do dzieła.

Ok, zobaczmy na tę metodę:

#[Route('/micro_post', name: 'app_micro_post')]
    public function index(MicroPostRepository $repository): Response
    {
        
        return $this->render('micro_post/index.html.twig', [
            'posts' => $repository->findAll(),
        ]);
    }

Zrobimy sobie podobną, gdzie wyszukuje posty o id większym niż 1:

#[Route('/querybuilder', name: 'app_micro_post_qb')]
    public function qb(MicroPostRepository $repository): Response
    {
        $posts_filtered = $repository->createQueryBuilder("m")
        ->where("m.id > 1")
        ->getQuery()
        ->execute();

        return $this->render('micro_post/index.html.twig', [
            'posts' => $posts_filtered,
        ]);
    }

Wygląda to tak:

  • Każde repository ma metodę createQueryBuilder, dziedziczoną jak wszystko w Symfony
  • Tworzymy jakiś alias, najlepiej jedna literka reprezentująca entity
  • Dodajemy where, jak w query builderze Laravela
  • Skoro jest hard-coded to nie musimy niczego bindować
  • Potem get query i execute

Wykorzystujemy już obecne template index, ale przekazujemy tam posty z query buildera. Rzućmy jeszcze okiem na klasę Repository:

class MicroPostRepository extends ServiceEntityRepository
{
    public function __construct(ManagerRegistry $registry)
    {
        parent::__construct($registry, MicroPost::class);
    }

    //    /**
    //     * @return MicroPost[] Returns an array of MicroPost objects
    //     */
    //    public function findByExampleField($value): array
    //    {
    //        return $this->createQueryBuilder('m')
    //            ->andWhere('m.exampleField = :val')
    //            ->setParameter('val', $value)
    //            ->orderBy('m.id', 'ASC')
    //            ->setMaxResults(10)
    //            ->getQuery()
    //            ->getResult()
    //        ;
    //    }

    //    public function findOneBySomeField($value): ?MicroPost
    //    {
    //        return $this->createQueryBuilder('m')
    //            ->andWhere('m.exampleField = :val')
    //            ->setParameter('val', $value)
    //            ->getQuery()
    //            ->getOneOrNullResult()
    //        ;
    //    }
}

Tam mamy wykomentowane przykłady jak tworzyć metody tego repozytorium, też mamy createQueryBuilder, też bardzo podobny mechanizm. W Laravelu mieliśmy fasadę DB oraz Eloquent ORM (i ogólnie dużo przejrzystych fasad, mniej dziedziczonych z góry metod, którymi trzeba umieć się posługiwać).

Cóż, Symfony jest trudniejsze i szukając Laravelowych analogii to najbardziej nasuwa się Local Query Scopes.

W Symfony wszystko co nie jest prostym wyszukiwaniem po id albo konkretnym polu równym coś (findBy, findOneBy, każde repo dziedziczy te metody) tworzy się tak, jak Local Query Scopes w Laravelu.

Jeżeli już trochę się Laravelem pobawiliśmy to po prostu potraktujemy to jako dziwactwo frameworka Symfony, ale jeżeli Symfony to coś, czego uczymy się jako pierwszy framework, może być trudno, chyba że rozumiemy dobrze SQL.