Poznajemy entity managera po raz pierwszy. Kontynuacja poprzednich lekcji o Symfony. Do dzieła.

Ok, przypomnijmy sobie tę metodę:

#[Route('/micro_post/{id}', name: 'app_micro_post_show')]
    public function showOne(int $id, MicroPostRepository $repository): Response
    {
        
        return $this->render('micro_post/single.html.twig', [
            'post' => $repository->find($id),
        ]);
    }

Wstrzykujemy repozytorium i używamy find, aby dostać entity. Teraz wersja z auto-wiring (odpowiednik route-model binding z Laravela):

#[Route('/micro_post/{post}', name: 'app_micro_post_show')]
    public function showOne(MicroPost $post): Response
    {
        return $this->render('micro_post/single.html.twig', ['post' => $post]);
    }

Ok, teraz zaimportujemy sobie EntityManagera:

use Doctrine\ORM\EntityManagerInterface;

I użyjemy go w podobny sposób co metoda pierwsza:

#[Route('/micro_post_entity/{id}', name: 'app_micro_post_show_entity')]
    public function showOneEntity(EntityManagerInterface $entityManager, int $id): Response
    {
        $post = $entityManager->getRepository(MicroPost::class)->find($id);
        return $this->render('micro_post/single.html.twig', ['post' => $post]);
    }

Ktoś może zapytać po co to jest, skoro i tak pobiera repozytorium. Cóż, w tym przypadku tak. Natomiast w Symfony jest wzorzec entity-repository i pewne rzeczy są oddzielone:

  • Entity to taki jakby model z Laravela
  • Repository to coś co służy zwracaniu pojedynczych entities oraz kolekcji
  • EntityManager to coś, co zapisuje do bazy danych/usuwa z bazy danych
  • Repository ma ograniczoną ilość query (znajdź jednego, przynieś wszystkie, znajdź jednego po kolumnie równej x, przynieś wszystkie po kolumnie równej x)
  • Repository ma metodę createQueryBuilder służącą do tworzenia query buildera w sposób podobny do Laravel local query scopes

Z uwagi na tę architekturę myślę, że warto było wprowadzić entity managera tak szybko, jak to możliwe.

Przykład z dokumentacji Symfony:

// src/Controller/ProductController.php
namespace App\Controller;

use App\Entity\Product;
use App\Repository\ProductRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
// ...

class ProductController extends AbstractController
{
    #[Route('/product/edit/{id}', name: 'product_edit')]
    public function update(EntityManagerInterface $entityManager, int $id): Response
    {
        $product = $entityManager->getRepository(Product::class)->find($id);

        if (!$product) {
            throw $this->createNotFoundException(
                'No product found for id '.$id
            );
        }

        $product->setName('New product name!');
        $entityManager->flush();

        return $this->redirectToRoute('product_show', [
            'id' => $product->getId()
        ]);
    }
}

Schemat działania:

  • Wstrzykujemy entity manager
  • EntityManager pobiera repozytorium klasy Product, repozytorium znajduje entity product o podanym id
  • To entity ma metodę setName, która jest użyta
  • EntityManager wykonuje flush, co sprawia, że w bazie danych zmiany zostaną zapisane

Więcej o tym niebawem, ale myślę, że warto to konceptualnie sobie rozłożyć, bo jest inaczej niż w Laravelu.