php - Есть ли удобное решение для сложных запросов?


2

Работая с Doctrine2 я заметил, что с ее помощью очень удобно сохранять данные сущностей, однако с выборками нужно существенно повозиться. Понятно, что это не проблема самой ORM, а скорее вопрос подходов, и все-же хочется найти удобное решение для формирования универсальных и сложных запросов.

Итак, пример будет как всегда самый простой: есть записи, теги к ним, картинки и автор. Задача тоже простая: получить список категорий.

И по мимо этого есть еще список определенных кейсов по оптимизации и фильтрации:

  • Список записей
  • Список записей с картинками
  • Список записей с тегами
  • Список записей с картинками и тегами
  • Список записей с картинками, тегами и автором
  • Список записей с картинками и тегами, где автор такой-то
  • Список записей с картинками и тегами, где автор такой-то и тег такой-то
  • Список записей где количество тегов больше 5, а рейтинг автора меньше 100 при условии, в в записи больше 1 картинки.

По сути это все упирается в 1 запрос, "получения списка записей", с фильтрацией и условиями. Однако реализовать подобное с помощью doctrine2 да и наверное голом SQL с PHP достаточно кодообъемно.

На всякий случай я приведу сюда пример решения от которого я отказался сразу. Это отдельный метод для каждого запроса, например:

$this->recordRepository->findList($first, $offset);
$this->recordRepository->findListWithTags($first, $offset);
$this->recordRepository->findListWithTagsAndImages($first, $offset);
$this->recordRepository->findListWithTagsAndImagesAndAuthor($first, $offset);
$this->recordRepository->findListWithTagsAndImagesAndAuthor($first, $offset);
$this->recordRepository->findListWithTagsAndImagesAndAuthorByAuthor($first, $offset, $userId);
$this->recordRepository->findListWithTagsAndImagesAndAuthorByAuthorAndTag($first, $offset, $userId, $tagId);
...

В общем таких комбинаций одного запроса может быть весьма много. В качестве преимущества можно рассмотреть удобство тестирования, но вот недостатки весьма перекрывают это дело: - например findListWithTags и findListWithTagsAndImages не несут в себе ничего для бизнес логики, а только внутреннюю оптимизацию. - очень сильно разрастается кол-во методов в репозитории - появляется некая грязь по коду, с теми-же условиями но внутри.

Пока мое решение, что-то вроде:

$this->recordRepository->findListByCondition($condition);

Где $condition, некий объект собирающий у себя условия. Этот подход выглядит весьма рабочий, однако имеет ряд недостатков:

  • Когда мы заполняем $condition нашими условиями, существует возможность дублирования в неких кейсах.
  • В репозитории нужно проанализировать $condition, в результате появляется множество условий
  • Сложность тестирования.

В общем хотелось бы получить совет или наводку на решение данного вопроса.

Источник
  •  51
  •  0
  • 11 янв 2018 2018-01-11 13:43:49
@Nepster что есть AR ? зы: сущности и репозитории там есть. — 11 янв 20182018-01-11 14:30:10.000000
@teran, в cakephp сидит AR. Мой вопрос не совсем из этой области. Если AR плохо дружит с абстракциями, но если в cakephp ввести сущности и репозитории, мы получите ту-же проблему. — 11 янв 20182018-01-11 14:27:27.000000
а в чем ваш метод плох? у вас 10 комбинаций -> вот и получается 10 разных кейсов. либо же вы можете делать 1 общий метод, который получить огромную пачку всего, что можно, заюзаете кеш и т.д — 11 янв 20182018-01-11 14:23:40.000000
Добавьте примерный код пары ваших методов. Ваш прошлый вопрос страдает тем же самым. — 11 янв 20182018-01-11 13:59:25.000000
странно, что нет динамической склейки методов, типа там ->findList()->findTags()->findImages, cakephp к примеру позволяет как по цепочками условия задавать, так и строить имя метода динамически findListTagsImages(), ну или около того. — 11 янв 20182018-01-11 13:52:21.000000

Ответов пока нет