Параметр indexBy атрибута OneToMany
Параметр indexBy атрибута OneToMany указывает,
по какому полю связанной сущности нужно проиндексировать
коллекцию. По умолчанию Doctrine возвращает коллекцию
с числовыми ключами от 0 до n.
Если задать indexBy, ключами станут значения
указанного поля. Это удобно, когда нужно быстро
получить элемент по известному значению поля,
например по slug или code.
Параметр принимает имя поля связанной сущности
в виде строки.
Синтаксис
#[OneToMany(mappedBy: 'field', targetEntity: Entity::class, indexBy: 'property')]
Пример
Давайте создадим сущность Article и связанную
с ней сущность Comment. Проиндексируем коллекцию
комментариев по полю code:
<?php
namespace App\Entity;
use App\Repository\ArticleRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ArticleRepository::class)]
class Article
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $title = null;
#[ORM\OneToMany(
mappedBy: 'article',
targetEntity: Comment::class,
indexBy: 'code'
)]
private Collection $comments;
public function __construct()
{
$this->comments = 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 getComments(): Collection
{
return $this->comments;
}
}
?>
Теперь создадим саму сущность Comment с полем code:
<?php
namespace App\Entity;
use App\Repository\CommentRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: CommentRepository::class)]
class Comment
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $code = null;
#[ORM\Column(type: 'text')]
private ?string $text = null;
#[ORM\ManyToOne(inversedBy: 'comments')]
private ?Article $article = null;
public function getId(): ?int
{
return $this->id;
}
public function getCode(): ?string
{
return $this->code;
}
public function setCode(string $code): static
{
$this->code = $code;
return $this;
}
public function getText(): ?string
{
return $this->text;
}
public function setText(string $text): static
{
$this->text = $text;
return $this;
}
public function getArticle(): ?Article
{
return $this->article;
}
public function setArticle(?Article $article): static
{
$this->article = $article;
return $this;
}
}
?>
Пример
Давайте получим статью и обратимся к её комментариям
по ключу code:
<?php
namespace App\Controller;
use App\Entity\Article;
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('/article', name: 'article_show')]
public function show(EntityManagerInterface $em): Response
{
$article = $em->getRepository(Article::class)->find(1);
$comment = $article->getComments()->get('abcde');
return new Response($comment->getText());
}
}
?>
Результат выполнения кода:
"hello"
Пример
Давайте переберём коллекцию и выведем все ключи,
полученные благодаря indexBy:
<?php
namespace App\Controller;
use App\Entity\Article;
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('/article/keys', name: 'article_keys')]
public function keys(EntityManagerInterface $em): Response
{
$article = $em->getRepository(Article::class)->find(1);
$res = [];
foreach ($article->getComments() as $code => $comment) {
$res[] = $code;
}
return new Response(implode(', ', $res));
}
}
?>
Результат выполнения кода:
"abcde, user, article"