Ответы пользователя по тегу Doctrine ORM
  • По какой причине при сохранении сущности с отношением one to many, не записывается id на связь?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Картинкам не надо знать о продуктах. Минимизируйте количество двусторонних ассоциаций.

    Так же почитайте про каскадные персисты.

    p.s. Подобные вопросы следует удалять так как "легко гуглится" или просто достаточно прочитать документацию. Не ленитесь иначе все будет и дальше плохо.
    Ответ написан
  • Как правильно работать с объектами выборки doctrine в Symfony?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    дополню ответ Юрий

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


    Все сущности заворачиваются в прокси объекты, что бы работала "магия" вроде ленивой подгрузки и т.д. Именно по этому в сущностях "больше" чем есть на самом деле.

    По поводу коллекций, в Doctrine есть такая штука как Collection. Вы должны понимать что в доктрине вы оперируете не табличками в базе, а объектами. Строите именно объектную модель вашей системы. В этом ключе можете почитать что такое "агрегат сущностей". В вашем случае у вас агрегат будет состоять из двух сущностей. Product и его Image. Например если вы захотите сделать добавление картинок, вы можете сделать так:

    /**
     * usage: $product->addImage($image);
     */
    public function addImage(Image $image)
    {
        $this->images->add($image);
    }


    А коллекция сама выполнит persist новой сущности. Таким образом количество репозиториев уменьшается до количества корней агрегатов сущностей. В вашем примере "корнем", то есть вершиной графа взаимоотношений объектов в контексте продуктов, является сам продукт. А потому репозиторий мы будем делать только для продуктов. Все остальное внутри оного разруливается либо при помощи коллекций.

    При работе с доктриной вообще полезно представлять себе, что никакой базы данных у вас нет. Что данные просто живут между запросами где-то там, в памяти. Это должно помочь вам "абстрагироваться" и перестать смешивать "сущности" и "таблицы".

    К примеру "новички" в доктрине любят персисть сущность даже для обновления. Они путают `persist` и `save`. Так вот, если вы загрузили сущность из базы через доктрину, то сущность уже попадает в unit of work. И делать persist уже не нужно, этот метод только для того чтобы доктрина узнала о чем-то новом. А так она и так знает про эту сущность. В итоге вы можете просто что-то поменять и вызвать flush. То есть репозиторий - это тупо хранилище. Хранилище умеет хранить. Изменять то, что оно хранит оно не может.

    Так же рекомендую на тему репозиториев почитать это:

    www.whitewashing.de/2013/03/04/doctrine_repositori...

    Ну и в целом.

    https://www.youtube.com/watch?v=rzGeNYC3oz0 - доклад о том как готовить доктрину от авторов оной.

    От себя лишь добавлю простые правила:

    - Не используйте напрямую доктриновские репозитории. Пишите свои, а в них уже юзайте доктриновские. Не стоит размазывать доктрину по всему проекту, потом это будет нереально поддерживать.
    - Не наследуйтесь от EntityRepository. Это внутренний механизм доктрины общего назначения. Используйте их в своих репозиториях со своим интерфейсом, повышая специфичность и ужесточая контроль за тем кто что юзает.
    - Старайтесь использовать entity manager только в своих репозиториях и каких то небольших сервисах. Не размазывайте все по всюду.

    что очень сильно срет память.


    Доктрина гарантирует вам что в памяти будет всегда только один инстанс сущности. То есть если у вас есть 10 объектов одного типа и имеющих один объект, это все будут ссылки на одну сущность. В вашем случае у вас просто циклическая ссылка между продуктами и изображениями. dump циклические ссылки не особо умеет.

    Это логичное ограничение, дабы не возникало ситуаций что вы обновили что-то в одном экземпляре сущности и что-то в другом, и в базу попадут только часть изменений. За подробностями - читайте документацию к доктрине в отношении UnitOrWork и Identity Map.
    Ответ написан
  • Репозиторий для поиска в БД?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    вроде return new Post($searchResult) ?


    php.net/manual/en/reflectionclass.newinstancewitho...

    То что вам предстоит написать называется гидраторы. Они берут стэйт и запихивают его в объект минуя методы (напрямую по мэппингу). Альтернатива - сделать статический метод конструктор который будет делать все то же самое но уже почти без рефлексий. Третий вариант - прокси классы (то как это делает доктрина).
    Ответ написан
  • Если ли смысл в ОРМ для моего случая?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Есть ли порог когда использование ОРМ становится неоправданым/оправданым? Где он?


    ORM-ки нужня для одного конкретного типа систем - OLTP (On-line Transaction Processing)

    У меня в приложении есть модуль который работает с бд Solr


    У вас есть документы, в документно ориентированных базах данных нет связей. Потому вам нужен Object Document Manager а не Object Relational Mapper.

    Каждый документ может имеет поле parent в котором сохранен ид-родителя, дальше ид-прародителя, дальше прапрародителя итд.


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

    бд в режиме read-only


    Тогда точно не нужна ORM/ODM.

    Итд. Иногда какая-то дополнительная трансформация.


    Но это же трансформация на уровне формирования результата выборки, так? Если так - то это опять же не та проблема.
    Ответ написан
    3 комментария
  • Как выбрать данные из таблицы для которой не создан класс ORM в symphony?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    DBAL, NativeSQL
    Ответ написан
    Комментировать
  • DQL запрос в symfony (связь много ко многим)?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    А как получить список акций, которых нет у заданного пользователя?


    Перефразируя. Вам нужен список акций всех пользователей кроме конкретного, нет?

    SELECT s.stockname FROM Stocker\StockBundle\Entity\Userstock s
    WHERE s.user != :user


    где :user это id юзера.

    Вообще такая штука. Если вы хотите оперировать SQL и т.д. то оперируйте. Напишите свой native query и т.д. А еще лучше - откажитесь от доктрины. Она хороша тогда, когда вы погружаетесь в предметную область и больше тратите время не на SQL/базы данные а на грамотное выстраивание взаимоотношений ваших сущностей.

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

    p.s. StockBundle это плохая идея. По сути если у вас есть что-то типа CoreBundle (общий бандл) - то вы уже проиграли в плане разделения логики на "отдельные части". Границы проведены неверно.
    Ответ написан
  • Как в Zend Framework 2 реализовать динамическое добавление связанных моделей?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    давайте думать. Нужно ли странице знать о своих тегах? Да, было бы прикольно но только что делать если теги нужно будет добавлять еще чему-нибудь? Или например кейсы когда какие-то теги надо создать а какие-то просто подключить.

    Так вот, убираем связь тегов из Page и оставляем однонаправленную ассоциацию на страницы у тегов. Теги нам делает какой-нибудь сервис (Tagger) с методами аля assignTags($page, $tags) и getTagsOf($page)

    Да, это суть сложнее зато можно спокойно реюзать в будущем, это проще поддерживать и вообще кошерно.
    Ответ написан
  • Проект со сложной логикой на Symfony – как проектировать? Примеры?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Как их организуете (их тогда будут сотни)?


    Раскидываю по неймспейсам. Скажем все действия относящиеся к юзерам находятся в папке Users.

    Только вы учитывайте что CQRS это прикольно но особо не нужно. К примеру это сразу подразумевает что вы используете UUID вместо автоинкрементов и прочей чуши. Можете сделать хотя бы как Дядя Боб предлагает в своей Clean Architecture. Просто сервис на каждое действие.

    Есть ли смысл выносить каждую доменную модель в модуль/микросервис


    Если вы не умеете писать монолиты так что бы потом все было относительно нормально, думать о микросервисах не стоит. Так же как делить проект на модули когда вы еще слабо представляете как прописывать границы этих модулей.

    Раньше для дополнительных действий мне достаточно было использовать что-то вроде beforeUpdate/afterCreate модели.


    ну а сейчас вы будете эти вещи в сервисы пихать. Причем возможно не в один сервис. Вообще старайтесь не делать "хуков" и не будет с ними проблем. Есть к примеру DomainEvents такая штука, ну и можно все эти "дополнительные действия" в хэндлерах команд делать.

    Как не превратить кидание/получение событий типа PostBeforeEdit/PostBeforeEditHandler в "callback hell"?


    Просто забудьте об этих ивентах.

    ACL. Где храните указанную логику?


    Есть в симфони security vouters, а дальше все зависит от того что вы делаете.

    Как вы версионируете подобные проекты? А если нужна "N-1" рабочая версия на продакшене?


    git + docker теги в мастере. Ветки нужно плодить только тогда, когда у вас система деплоится кастомерам и нужно поддерживать сразу кучу версий. Называется это gitflow.

    На какие проекты (точнее, на код) можете посоветовать посмотреть для лучшего понимания? Ссылки на репозитории?

    На гитхабе катострофически мало примеров хороших приложений на симфони. Да и не только на симфони - в принципе найти в открытом доступе сложный проект - это нереально. NDA и все такое. Такие системы обычно очень дорогие и закрытые со всех сторон.

    p.s. почитайте книжки:

    - Эрик Эванс - Предметно ориентированное проектирование
    - Крэйг Ларман - Применение UML 2.0

    p.p.s. Все ваши загоны не имеют никакого смысла если вы не будете пользоваться практиками вроде Test-Driven-Development, ну или хотя бы покрывать систему интеграционными тестами. Без этого вы не сможете делать частный мелкий рефакторинг, а без этого ваша система быстро превратится в легаси.
    Ответ написан
  • В каком месте правильно писать запросы в symfony 3?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    В репозиториях.
    Ответ написан
    Комментировать
  • Для чего inversedBy и mappedBy в Doctrine и в чём разница?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Для объявления двусторонних связей между сущностями. Справедливости ради - в 99% случаев двусторонние связи не нужны и их лучше по возможности избегать. Как минимум потому что они не нужны и позволяют делать страшные вещи, ну и на производительность сказывается это пагубно.
    Ответ написан
    Комментировать
  • Легковесная Data Mapper PHP ORM?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    да и для проекта она тяжеловата.


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

    В целом рекомендую глянуть на Spot2 или analogue, но количество "лишнего" для молодого проекта кода будет намного выше чем в случае с доктриной.

    Если же вам нужен именно data mapper а не ORM, то... тут сложно, все что я видел так себе. Из интересных проектов разве что https://github.com/idr0id/Papper порекомендую.
    Ответ написан
    Комментировать
  • Оправданно ли использование doctrine в хелпер классе symfony 3?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    container-aware - знает про контейнер и может работать с ним, чего по хорошему оно не должно уметь делать.

    Хочу писать написать функцию которая достает записи из бд по id.


    Записи из БД или сущности? Это вопервых весьма большая разница, а во вторых уже же есть старый добрый $em->find(Entity::class, $id), парам конвертеры дефолтные и т.д

    функцию в хелпер классе который будет находиться тут AppBundle\Utils


    Вообще это весьма плохая идея. И про то что будет глобальная функция которая этим будет заниматься, и то что вы ее как статику в класс запихаете а не сервис сделаете, и то что Utils... это называется "мне было лень придумывать адекватное название".
    Ответ написан
    3 комментария
  • Оптимизирует ли Symfony/Doctrine запросы к сущности?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    в смысле кеширует ли волшебным образом? нет. Единственная оговорка - если вы это делаете на коллекции и все данные из коллекции уже загружены в память - то тогда да, оно просто посчитает количество объектов, подходящих под критерию (метод matching для фильтрации коллекций). А так... только выборки по первичному ключу в случае если сущность уже загружена.
    Ответ написан
    2 комментария
  • Doctrine архитектура и построение связей, как правильно?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    философия доктрины - мы проекируем систему исходя из взаимодействия объектов, база данных лишь деталь реализации.

    То есть у нас есть объекты User, UserEmail и UserCode. У объекта User есть поля emails и codes. Иии все. При желании мы можем сделать bidirectional связь и тогда у UserEmail/UserCode появится поле user, которое будет содержать владельца, но как правило это не нужно.
    Ответ написан
    Комментировать
  • Что отличает сущность вызванную Doctrine (методом find) от той которую мы сами создали?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Ведь тот же метод $em->persist(...); мы используем и для обновления записи.


    Вообще-то нет. По умолчанию persist используется для того, что бы добавить сущность в UnitOfWork. Вызывая его доктрина начинает разбираться, нам надо просто замерджить сущность в текущий UoW или добавить ее в очередь на вставку.

    Вызывать persist при обновлении не нужно вовсе, можно обойтись merge, и только если у нас используется политика отслеживания изменений deferred-explicit, но это нужно в очень редких случаях. Например когда в рамках одного запроса мы должны загрузить из базы сотню-другую сущностей а обновить одну. В этом плане данная политика отслеживания изменений сильно ускоряет работу UoW, так как мы явно указываем за какими сущностями нам следить (сложность алгоритма UoW - O(N), так что чем меньше N тем быстрее работает). Единственное НО - это сильно усложняет работу с entity manager (по хорошему em должен быть только в репозитории), и в принципе ломает красивую концепцию persistence ignorance, так что использовать ее нужно только тогда, когда есть проблемы с производительностью UoW.

    через каждые 30 насколько изменится скорость переноса?

    Да, это ускорит работу. Единственное что, если вы занимаетесь вставкой большого количества объектов, имеет смысл после каждого flush делать clear, отчищать unit-of-work, поскольку вставленные сущности будут крутиться в нем, и после каждого flush их количество будет увеличиваться и скорость будет падать.
    Ответ написан
  • Как в Doctrine 2.5 указать связь на non-ID стобец?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Философия доктрины заключается в том, что база данных это деталь реализации, а вы должны проектировать бизнес-сущности, связи между ними и их взаимодействие. База данных в этом случае должна целиком и полностью генериться.

    То что вы хотите сделать идет в разрез с философией Doctrine. Организовать подобную связь нельзя. Можно джойнить что угодно с чем угодно в запросах, но не более.
    Ответ написан
    1 комментарий
  • Как выполнить запрос из одного сервиса к другому и создать объект app-platform(doctrine)?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Перестаньте использовать "таблицы" и "записи" и используйте "объекты".

    Doctrine исповедует принцип persistence ignorance. То есть дает вам определенный уровень изоляции от хранилища данных.

    У вас есть репозитории, у вас есть сущности. Попробуйте описать что вы хотите сделать используя эти термины, при том что сущности доктрины это просто PHP объекты, ничего особенного.
    Ответ написан
    6 комментариев
  • В каких случаях удобно использовать поле EntityID вместо дополнительных таблиц?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    вам нужно наследование (table inheritance) и разные типы объектов для разных типов нотификаций. Это если брать "обычно".

    p.s. при работе с доктриной проще оперировать сущностями и взаимоотношением оных а не таблицами. Это domain-centric штука, а не data-centric.
    Ответ написан
  • Как правильно создать модель в symfony с именем 'transaction'?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    переименуйте сущность и все будет хорошо. Таблицы желательно называть во множественном числе (transactions). И вообще лучше избегать использования зарезервированных слов в названиях таблиц или полей таблиц.
    Ответ написан