Объект передачи данных – это элемент, используемый для передачи данных между различными местами приложения. Его единственная роль сводится к хранению данных. В нем нет никакой логики.
Давайте предположим, что нам нужны данные из базы данных для создания некоторого отчета. Есть множество способов сделать это. Мы можем извлекать сущности, а затем получать интересные данные от этих сущностей. Однако, вероятно, это будет не самый оптимальный способ. Мы также можем получить исходные данные из базы данных. Но тогда не будет проверки типов и так далее. В Доктрине есть более простой способ.
Доктрина версии 2.4 позволяет извлекать данные относительно очень приятным способом. Он создает объекты для нас, устанавливая правильные типы, которые класс имеет в конструкторе. Единственным ограничением является то, что объекты могут быть созданы из скалярных типов.
Давайте предположим, что есть две сущности: Пользователь и Доход.
/**
* @ORM\Entity()
*/
class User
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private ?int $id;
/**
* @ORM\Column(type="string", length=255, nullable=false)
*/
private string $fullName;
/**
* @var Collection
* @ORM\OneToMany(targetEntity="Income", mappedBy="user")
*/
private Collection $incomes;
//…
}
/**
* @ORM\Entity()
*/
class Income
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private ?int $id;
/**
* @ORM\ManyToOne(targetEntity="User", inversedBy="incomes")
* @ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private User $user;
/**
* @ORM\Column(type="datetime", nullable=false)
*/
private \DateTime $when;
/**
* @ORM\Column(type="integer", nullable=false)
*/
private int $income;
//...
}
База данных содержит такие данные:
Как показано выше, в каждом месяце есть два пользователя с определенным доходом.
Для отчета требуется весь доход пользователя, поэтому класс DTO может выглядеть следующим образом:
class UserIncome
{
private string $fullName;
private int $income;
public function __construct(string $fullName, int $income)
{
$this->fullName = $fullName;
$this->income = $income;
}
public function getFullName(): string
{
return $this->fullName;
}
public function getIncome(): int
{
return $this->income;
}
}
Чтобы получить агрегированные данные, нам нужно использовать конструктор запросов для создания запроса:
$result = $this->entityManager->createQueryBuilder()
->select(sprintf(
'NEW %s(u.fullName, SUM(i.income))',
UserIncome::class
))
->from(User::class, 'u')
->leftJoin('u.incomes', 'i')
->where('YEAR(i.when) = 2020')
->groupBy('u.fullName')
->getQuery()
->getResult();
Создание объектов DTO происходит путем добавления НОВОГО оператора с полным именем класса с конкретными аргументами конструктора.
Результаты следующие:
Описанный выше способ значительно облегчает создание объектов передачи данных. Вместо того, чтобы извлекать целые объекты и извлекать из них данные, мы можем немедленно извлекать объекты, заполненные данными. Благодаря этому мы можем сэкономить много процессорных циклов, а также избежать написания большего количества строк кода
Оригинал: “https://dev.to/jszutkowski/fast-way-to-create-dto-using-doctrine-2dlf”