Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Создание, чтение, изменение, удаление

Сущность сама себя не сохраняет. Этим занимается EntityManager: ему сообщают, какие объекты нужно записать, а он выполняет запросы. Читают данные через репозиторий — класс, созданный вместе с сущностью.

Создание записи

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('Первая статья');
    $post->setBody('Текст статьи');
 
    $em->persist($post);
    $em->flush();
 
    return new Response('Создана статья №' . $post->getId());
}

persist() сообщает Doctrine о новом объекте, flush() выполняет запрос INSERT. До вызова flush() в базе ничего не меняется.

Чтение

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(),
    ]);
}
МетодЧто возвращает
find($id)Запись по идентификатору или null
findAll()Все записи
findBy([...])Записи по условиям
findOneBy([...])Первую подходящую запись или null
count([...])Количество
$latest = $posts->findBy(
    ['published' => true],
    ['id' => 'DESC'],
    10,
);

Аргументы findBy(): условия, сортировка, сколько записей взять.

Сущность прямо в аргументах

Если в адресе есть {id}, а в аргументах метода — сущность, Symfony найдёт запись сам. Не нашёл — вернёт ошибку 404:

#[Route('/blog/{id}', name: 'blog_show')]
public function show(Post $post): Response
{
    return $this->render('blog/show.html.twig', ['post' => $post]);
}

Для поиска по другому полю его указывают в адресе: /blog/{slug:post}.

Изменение

Объект, полученный из базы, Doctrine уже отслеживает. Достаточно изменить его и вызвать 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() здесь не нужен.

Удаление

$em->remove($post);
$em->flush();

Несколько изменений сразу

flush() записывает все накопленные изменения одной транзакцией: либо выполнятся все запросы, либо ни один.

$em->persist($post);
$em->persist($comment);
$author->setPostCount($author->getPostCount() + 1);
 
$em->flush();

Частая ошибка

Без flush() данные не сохраняются: persist() только ставит объект в очередь. Код отработает без ошибок, а в базе ничего не появится. И наоборот — не вызывайте flush() в цикле после каждой записи: один вызов после цикла выполнится во много раз быстрее.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.