РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
191 of 258 menu

Параметр fetch атрибута OneToMany

Параметр fetch атрибута OneToMany определяет стратегию загрузки связанных сущностей из базы данных. Первым значением передаётся константа из класса Doctrine\ORM\Mapping\ClassMetadata. Доступны значения LAZY, EAGER и EXTRA_LAZY. По умолчанию используется LAZY.

Синтаксис

#[OneToMany( mappedBy: property, targetEntity: Entity::class, fetch: 'LAZY' )]

Пример

Давайте создадим сущность Category со связью OneToMany на сущность Article со стратегией загрузки LAZY:

<?php namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] class Category { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\Column(length: 255)] private ?string $title = null; #[ORM\OneToMany( mappedBy: 'category', targetEntity: Article::class, fetch: 'LAZY' )] private Collection $articles; public function __construct() { $this->articles = new ArrayCollection(); } public function getId(): ?int { return $this->id; } public function getTitle(): ?string { return $this->title; } public function setTitle(string $title): static { $this->title = $title; return $this; } public function getArticles(): Collection { return $this->articles; } } ?>

Теперь создадим сущность Article с обратной связью ManyToOne:

<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] class Article { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\Column(length: 255)] private ?string $title = null; #[ORM\ManyToOne( inversedBy: 'articles', targetEntity: Category::class )] #[ORM\JoinColumn(nullable: false)] private ?Category $category = null; public function getId(): ?int { return $this->id; } public function getTitle(): ?string { return $this->title; } public function setTitle(string $title): static { $this->title = $title; return $this; } public function getCategory(): ?Category { return $this->category; } public function setCategory(?Category $category): static { $this->category = $category; return $this; } } ?>

При стратегии LAZY связанные статьи загружаются из базы данных только в момент первого обращения к коллекции:

<?php namespace App\Controller; use App\Entity\Category; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class ArticleController extends AbstractController { #[Route('/category/{id}', name: 'category_show')] public function show(int $id, EntityManagerInterface $em): Response { $category = $em->getRepository(Category::class)->find($id); $count = $category->getArticles()->count(); return new Response('Count: ' . $count); } } ?>

Результат выполнения кода для категории с тремя статьями:

"Count: 3"

Пример

Давайте изменим стратегию загрузки на EAGER, чтобы связанные статьи загружались сразу вместе с категорией:

<?php namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] class Category { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\Column(length: 255)] private ?string $title = null; #[ORM\OneToMany( mappedBy: 'category', targetEntity: Article::class, fetch: 'EAGER' )] private Collection $articles; public function __construct() { $this->articles = new ArrayCollection(); } public function getId(): ?int { return $this->id; } public function getTitle(): ?string { return $this->title; } public function setTitle(string $title): static { $this->title = $title; return $this; } public function getArticles(): Collection { return $this->articles; } } ?>

Теперь при загрузке категории все связанные статьи будут загружены немедленно одним дополнительным запросом:

<?php namespace App\Controller; use App\Entity\Category; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class ArticleController extends AbstractController { #[Route('/category/{id}', name: 'category_show')] public function show(int $id, EntityManagerInterface $em): Response { $category = $em->getRepository(Category::class)->find($id); $titles = []; foreach ($category->getArticles() as $article) { $titles[] = $article->getTitle(); } return new Response(implode(', ', $titles)); } } ?>

Результат выполнения кода:

"article 1, article 2, article 3"

Пример

Давайте используем стратегию EXTRA_LAZY, которая позволяет выполнять операцию count без загрузки всей коллекции в память:

<?php namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity] class Category { #[ORM\Id] #[ORM\GeneratedValue] #[ORM\Column] private ?int $id = null; #[ORM\Column(length: 255)] private ?string $title = null; #[ORM\OneToMany( mappedBy: 'category', targetEntity: Article::class, fetch: 'EXTRA_LAZY' )] private Collection $articles; public function __construct() { $this->articles = new ArrayCollection(); } public function getId(): ?int { return $this->id; } public function getTitle(): ?string { return $this->title; } public function setTitle(string $title): static { $this->title = $title; return $this; } public function getArticles(): Collection { return $this->articles; } } ?>

При вызове count на коллекции с стратегией EXTRA_LAZY Doctrine выполнит отдельный SQL-запрос COUNT, не загружая сами сущности:

<?php namespace App\Controller; use App\Entity\Category; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Attribute\Route; class ArticleController extends AbstractController { #[Route('/category/{id}/count', name: 'category_count')] public function count(int $id, EntityManagerInterface $em): Response { $category = $em->getRepository(Category::class)->find($id); $count = $category->getArticles()->count(); return new Response('Total: ' . $count); } } ?>

Результат выполнения кода:

"Total: 3"

Смотрите также

  • атрибут OneToMany,
    который создаёт связь один-ко-многим
  • параметр mappedBy,
    который указывает обратное поле связи
  • параметр cascade,
    который задаёт каскадные операции
  • параметр orphanRemoval,
    который удаляет осиротевшие сущности
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить