Symfony symfony, репозитории, качественный lazy load

bars80081

Новичок
Добрый день,

пытаюсь пробиться сквозь тонны документации и несколько подзавяз в этом болоте. решил здесь спросить, авось кто выложит ссылочки на конкретные решения вопроса.

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

к примеру:

PHP:
$em = $this->getDoctrine()->getManager();

$blog1 = $em->getRepository('BloggerBlogBundle:Blog')->findOneBy(array('id' => 11));
$blog2 = $em->getRepository('BloggerBlogBundle:Blog')->findOneBy(array('id' => 12));
$blog3 = $em->getRepository('BloggerBlogBundle:Blog')->findOneBy(array('id' => 11));
даст три запроса в БД, хотя первый и третий идентичны. ну ладно, я конечно могу тут придумать своё хранилище, складывать туда объекты и проверять их наличие. но это фактически приводит к отказу от существующей системы репозиториев и написанию своей. уверен, в доктрине или самом symfony это уже сделано, но прокопаться через доки пока не получается.

вопрос1: как правильно выглядят в symfony запросы, если требуется ленивая загрузка, чтобы лишний раз ничего не грузилось?
вопрос2: можно ли накидать в очередь на загрузку идентификаторов, чтобы они потом загрузились при первом требовании?

второй вопрос вытекает из той методики, когда при подъёме данных по одной сущности можно складировать связи на другие сущности в очередь, а затем одним махом выбрать все при первом требовании объекта.

к сожалению, чтение доков по symfony и доктрине пока пользы не приносит, поэтому рад был бы, если кто-нибудь ткнул бы в конкретное место, как это делается. или пример какой.
ещё есть чуйка, что даже если в базовом наборе симфони и доктрины подобный подход не реализован, то он наверняка уже лежит готовенький на каком-нибудь ресурсе меценатов, вроде knpbundles.com. однако, там ещё хуже свалка, чем документация в той же доктрине

и ещё есть пара смежных вопросов:

на одном ресурсе увидел формулировку, что "Зависимостей между бандлами быть не должно. Они могут зависеть от библиотек. но не от бандлов. ".
вопрос3: как быть в случае, если используются общие сущности и репозитории?
к примеру, реестр пользователей может потребоваться сразу в нескольких бандлах. дело программиста - не дублировать код, поэтому репозиторий конечно должен быть один. где ему тогда находиться?

вопрос4: как, едрить его, выглядит простой запрос SELECT COUNT(*) FROM .... ?

куда не ткну, все занимаются какой-то анархией: либо выбирают коллекцию объектов (которая может быть нафиг не нужна) и потом уже ->count() от неё даёт число, на ровном месте перенапрягая систему, либо тупо фигачат прямой SQL-запрос чуть ли не в обход подготовки запросов в PDO, то есть выкидывают в мусорку достижения доктрины и симфони

спасибо
 

Вурдалак

Продвинутый новичок
на одном ресурсе увидел формулировку, что "Зависимостей между бандлами быть не должно. Они могут зависеть от библиотек. но не от бандлов. ".
вопрос3: как быть в случае, если используются общие сущности и репозитории?
к примеру, реестр пользователей может потребоваться сразу в нескольких бандлах. дело программиста - не дублировать код, поэтому репозиторий конечно должен быть один. где ему тогда находиться?
Это всё обман: бизнес-кода в бандлах вообще быть не должно. Бандл — это код для связки твоего бизнес-кода с фреймворком.

вопрос4: как, едрить его, выглядит простой запрос SELECT COUNT(*) FROM .... ?
ORM предназначена в первую очередь для write models, а читать можно как тебе угодно.
Но если в коде нет разделения на write models и read models, то, конечно, это понять не получится.

даст три запроса в БД, хотя первый и третий идентичны
Мне кажется, тут проблема в том, что Doctrine не может осознать, что полученный тобой критерий (['id' => 11]) является запросом по primary key. То есть, для Doctrine неочевидно сущность с каким идентификатором должна вернуться, т.к. она не анализирует набор переданных полей в этом методе. Но это я так предполагаю, я не пользуюсь этим продуктом. Там по идее должен быть просто find($id) или что-то такое.
 

AmdY

Пью пиво
Команда форума
Какую-то странную документацию ты читал. В доктрине есть запросы для вытаскивания нескольких записей одним запросом, есть идентити мэп, есть лениваая загрузка и юнит оф ворк, есть dql для запросов вроде count(*) Перекуривай мануалы и избавляйся с помощью DI от треша
$this->getDoctrine()->getManager()->getRepository('BloggerBlogBundle:Blog')
 

bars80081

Новичок
Какую-то странную документацию ты читал
я так понял, что http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/ - официальная. или нет? есть другой мануал?

есть идентити мэп, есть лениваая загрузка и юнит оф ворк
в том то и проблема, что найти не получается как и где. на ресурсе ни в разделах (к примеру, php-mapping и batch-processing ничего под свои вопросы), ни поиском по identity map, lazy load, unit of work ничего не находит.

есть dql для запросов вроде count(*)
но ведь DQL это прямые запросы. то есть вы советуете отказаться от QueryBuilder вообще?

избавляйся с помощью DI от треша
под DI подразумевается doctrine interface или что-то иное?
 

AmdY

Пью пиво
Команда форума
Вот IM, которое объясняет почему не будет двух запросов при одном ID как ты предполагал в первом вопросе
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/working-with-objects.html#entities-and-the-identity-map
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork.html

QueryBuilder лучше использовать, но он генерит как раз DQL и решает вашу проблему с count запросами. По ссылке приведённой вами же там есть вариант с count.
 

bars80081

Новичок
Сверху