Что делать, если нужно получить часть данных сущности?

Всем привет. Представим есть код:
interface Post
{
      public function getName(): string;

      public function getDescription(): string;

     public function getText(): string;
}

interface PostRepository
{
       public function findall()
      {

      }
}


Как бы все работает, все хорошо. Но к примеру, нам в сайдбаре нужно вывести список последних постов за неделю. Из данных нам нужно только название поста (getName) и короткое описание (getDescription). Если мы будем заполнять эти данные из репозитория, то сущность у нас будет не полной (getText == null), а если мы будем получать все данные, то сущность будет избыточной. (Я сильно упростил пример, у Post может быть тонна других зависимостей)

Как быть в таких случаях?
  1. Делать отдельный репозиторий и отдельную сущность
  2. Использовать stdClass[] или array[]


На проекте нет Doctrine, поэтому Proxy объекты для связей отсутствуют. Т.е. findAll / findOne из репозитория всегда вернет полный объект, даже если нужна часть этого объекта. Как вы решаете эту проблему у себя?
  • Вопрос задан
  • 195 просмотров
Решения вопроса 2
Maksclub
@Maksclub Куратор тега PHP
maksfedorov.ru
Для отображения используйте DTO и доставайте их из репозитория. Для логики отображения негоже сущности из бизнес-слоя вытягивать.

1 способ — заюзать Доктрину
сразу не увидел, что вы без нее работаете

Доктрина умеет создавать дтошки из коробки
class PostDTO
<?php

namespace App\DTO;

class PostDTO
{
    /** @var string */
    private $name;
    
    /** @var string */
    private $description;
    
    /** @var string */
    private $text;
    
    public function __construct(string $name, string $description, string $text)
    {
        $this->name = $name;
        $this->description = $description;
        $this->text = $text;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getDescription()
    {
        return $this->description;
    }

    public function getText()
    {
        return $this->text;
    }
}

И используя синтаксис NEW DQL создаем наши DTO :
$query = $em->createQuery('SELECT NEW App\DTO\PostDTO(p.name, p.description, p.text) FROM App\Entity\Post p');
$users = $query->getResult(); // array of PostDTO

Источник: https://www.doctrine-project.org/projects/doctrine...

2 способ — заюзать DBAL/PDO
Сделать запросы через более низкую прослойку без ORM (например через Doctrine DBAL или PDO) и результат фетчить в те же самые PostDTO в репе
Ответ написан
balykhinAS
@balykhinAS
Пишу на php
частичный объект это все еще объект?))

быть может стоит создавать нечто подобное https://github.com/ElisDN/demo-project-manager/blo...
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
SilenceOfWinter
@SilenceOfWinter
та еще зажигалка...
1. "lazy loading" - в конструктор передаем обязательные к заполнению параметры, остальные данные подгружаем из базы по мере вызова методов т.е.
public function getText(): string
{
    if ($this->text === null) {
        $this->loadData();
    }
    return $this->text;
}

2. Использовать класс хэлпер, например, нужны breadcrumbs, создаем в хэлпере метод getBreadcrumbs в который передается массив Post объектов, метод извлекает данные из объектов и получает недостающие данные одним запросом сразу для всех постов.
Ответ написан
@dmitriylanets
я бы предложил исполльзовать объект-критерии выборки
тогда мы сможем использовать полное и не полное получение данных, ну и для удобство фильтрации
$posts = $postRepo->findAllByCriteria( (new PostSearchCriteria)->withFullData(true) );
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы