Рубрики
Uncategorized

Получайте Результаты Из Doctrine В Виде DTO

Объект передачи данных – это элемент, используемый для передачи данных между различными местами приложения. Это всего лишь… Помеченный php, doctrine, orm.

Объект передачи данных – это элемент, используемый для передачи данных между различными местами приложения. Его единственная роль сводится к хранению данных. В нем нет никакой логики.

Давайте предположим, что нам нужны данные из базы данных для создания некоторого отчета. Есть множество способов сделать это. Мы можем извлекать сущности, а затем получать интересные данные от этих сущностей. Однако, вероятно, это будет не самый оптимальный способ. Мы также можем получить исходные данные из базы данных. Но тогда не будет проверки типов и так далее. В Доктрине есть более простой способ.

Доктрина версии 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”