Create, read, update, delete
An entity does not save itself. The EntityManager does that: you tell it which objects to write, and it runs the queries. Data is read through a repository — the class created together with the entity.
Creating a record
use App\Entity\Post;
use Doctrine\ORM\EntityManagerInterface;
#[Route('/blog/create', name: 'blog_create')]
public function create(EntityManagerInterface $em): Response
{
$post = new Post();
$post->setTitle('First post');
$post->setBody('The text of the post');
$em->persist($post);
$em->flush();
return new Response('Created post #' . $post->getId());
}persist() tells Doctrine about a new object, flush() runs the INSERT query. Nothing changes in the database before flush() is called.
Reading
use App\Repository\PostRepository;
#[Route('/blog', name: 'blog_index')]
public function index(PostRepository $posts): Response
{
return $this->render('blog/index.html.twig', [
'posts' => $posts->findAll(),
]);
}| Method | What it returns |
|---|---|
find($id) | A record by its identifier, or null |
findAll() | All records |
findBy([...]) | Records matching conditions |
findOneBy([...]) | The first matching record, or null |
count([...]) | The number of records |
$latest = $posts->findBy(
['published' => true],
['id' => 'DESC'],
10,
);The arguments of findBy(): conditions, ordering, how many records to take.
An entity right in the arguments
If the address has {id} and the method arguments include an entity, Symfony finds the record by itself. If there is none, it returns a 404 error:
#[Route('/blog/{id}', name: 'blog_show')]
public function show(Post $post): Response
{
return $this->render('blog/show.html.twig', ['post' => $post]);
}To search by another field, name it in the address: /blog/{slug:post}.
Updating
Doctrine already tracks an object fetched from the database. Just change it and call flush():
#[Route('/blog/{id}/publish', name: 'blog_publish', methods: ['POST'])]
public function publish(Post $post, EntityManagerInterface $em): Response
{
$post->setPublished(true);
$em->flush();
return $this->redirectToRoute('blog_show', ['id' => $post->getId()]);
}persist() is not needed here.
Deleting
$em->remove($post);
$em->flush();Several changes at once
flush() writes all accumulated changes in one transaction: either every query runs or none does.
$em->persist($post);
$em->persist($comment);
$author->setPostCount($author->getPostCount() + 1);
$em->flush();Common mistake
Without flush() data is not saved: persist() only queues the object. The code runs without errors, and nothing appears in the database. And the other way round — do not call flush() in a loop after every record: one call after the loop is many times faster.