Вадим
К Доктору?
Михаил
КАКАЯ РЕКЛАМА? Я про докозательство опыта!
Вадим
а то тут каждый чото сказал да всё как-то мимо или юзай каскад постгреса. Думаю нифига народ, такие все умные а как оно у них удаляется внутри - никто и не знает толком
Вадим
Я бы на твоём месте прислушался к человеку. Он проект https://beta.scouts.su чисто на symfony + doctrine написал и всё там с ооп нормально.
я ваще всегда только за всё хорошее и против всего плохого, но 3й день это перебор, ей-богу
Михаил
а то тут каждый чото сказал да всё как-то мимо или юзай каскад постгреса. Думаю нифига народ, такие все умные а как оно у них удаляется внутри - никто и не знает толком
Слушай, вот я понимаю когда тут задают концептуальные вопросы или архитектураные или вопросы "а как лучше сделать" Но вопросы из разряда "а как оно работает". Да блин ну тебе ссылок накидали как оно работает. Возми консольную команду или тест сделай и посмотри по логам бд или по дебагеру как оно работает
Михаил
Я вот стараюсь не делать множественные связи или стараюсь удалять вручную Другие я думаю так же делают. Но это не значит что "говно ваше ооп, говно ваша доктрина" Иснтрумент есть, механизм есть. Им пользуются - просто не те кто в свой выходной готовы ответить. Настанет понедельник переформалируй вопрос и задай ещё раз. Потому что Твоё "вот какая-то ошибка падает при удалении" до сих пор осталась загадкой
Вадим
а тест отрабатывает локально отлично
Михаил
так что за ошибка. Какой рестрикшен её триггерит?
Doctor
А чо там за ошибка-то была? "Foreign key violation"? На проде и на локалке одинаковое окружение? Версии БД и всяких там доктрин-бандлов совпадают?
Михаил
Может ты миграцию криво накатил и у тебя 2 индекса на поле Или у тебя есть ещё одна таблица которая требует этой связи но она не помечена как orphan
Вадим
А чо там за ошибка-то была? "Foreign key violation"? На проде и на локалке одинаковое окружение? Версии БД и всяких там доктрин-бандлов совпадают?
да всё вроде одинаковое, 16 постргря, только локально оно в контейноре а на таймвебе он в таймвебном "класторе"
Вадим
хз чо там может отличаться
Doctor
Ну тут мне видится два варианта. 1. Deferred blabla. 2. Написать класс-удалялку для твоей сущности, которая всё за ней подчищает. Что ты в итоге и сделал, похоже. Т.е. лично я б выбрал что-то одно из этого. Может, кто-нибудь предложит более подходящие варианты
Вадим
Ну тут мне видится два варианта. 1. Deferred blabla. 2. Написать класс-удалялку для твоей сущности, которая всё за ней подчищает. Что ты в итоге и сделал, похоже. Т.е. лично я б выбрал что-то одно из этого. Может, кто-нибудь предложит более подходящие варианты
Да, у меня сначала не было такого класса, просто везде расставил orphanRemovable: true, написал тест, всё круто, отнёс на стейджинг, там не круто. Я притащил себе БД, написал юзкейз явного удаления, только сделал через удаление элементов коллекции и понадеялся снова на orphanRemovable: true, оно начало ругаться на ограничение null в форин ключе. Ну тут я и заебался и написал явное удаление каждого элементика через remove энтити менеджера. Вот.
Doctor
Подходящий вариант - разобраться со связями и докой. Слишком типичный кейс - каскадное удаление
Ну тут +1. Хочешь сделать что-то хорошее из чего-то непонятного = гуглишь, куришь маны, проводишь эксперименты, изучаешь логи. Зачастую вопрос лишь в том, хочешь ли ты выполнить задачу хорошо или быстро)
Вадим
толкьо ни в одной доке не написано можно ли это делать при ограничении NOT NULL на форин ключе
Павел
ну доку по связям я прочитал сегодня не 1 раз
Ну например orphanRemovable это не совсем про каскады. Как вариант везде ставить cascade remove + orphanRemove (тут осторожнее, просто это как бы использование всего). Но разобраться с инициаторами связей
Павел
А сама доктрина этого не делает
Вадим
не нужно там вообще делать setRelation(null)
хм.. ну это мне скаффолдер написал так.. а я чот не подумал
Вадим
может и правда не надо
Павел
у вас если свойство не может быть null и в бд не null, зачем ставить null?
Юра
Удаление вообще всегда сложнее вставки
Юра
Поэтому многие делают софт делит и не парятся
Вадим
Удаление вообще всегда сложнее вставки
так отож, я тут целый продукт написал, а удалять учился 3 дня, заказчик в непонятности
Юра
Вывод ты сделал правильный
Юра
Вручную описать все
Юра
Все эти каскады и орфаны приведут к тому что через пол года никто не поймет что происходит там
Юра
Единственное я не понял зачем ты там разные репозитории используешь вместо em->remove()
Юра
Я заметил что чем больше проект тем явнее должно всё быть. Явные удаления к примеру.
Юра
А то потом приходит новый разраб, где-то удалил энтити и оно пол базы потянуло автоматически
Юра
Подытоживая такая философия, краткий код в долгой перспективе не обязательно лучше чем длинный и явный. В го например куча всего пишется явно за что одни его матюкают а другие говорят что в этом секрет его успеха
Михаил
Ох, если идти от обратного то боюсь мы найдём языки где описание всего кода явно НЕ пойдёт читаемости на пользу. А значит скорее всего это не верная логика. Вручную описать всё нужно если ты не знаешь как это сделать коротко или правильно, но тебе нужен результат (ведь ради результата мы код и пишем.) А вот уже потом можно будет отрефакторить и сократить код
Юра
Помню когда была симфа 2 и я смотрел на руби он рейлс то меня тошнило от того сколько там всего неявно под капотом происходит. Какие-то переменные которые непонятно откуда берутся. Какое-то поведение которое нигде не описано и ты его не ожидаешь. И т.д.
Юра
Добавь туда ещё ивенты, непонятно какие листенеры их слушают и что делают. А ещё листенеры могут ещё что-то удалить. И там ещё листенеры по цепочке. Короче эта кроличья нора может быстро стать слишком глубокой
Михаил
Ну про листенеры я писал тут. Если определить что можно в них делать а что нельзя - то правильно расставив приоритеты можно избавиться от головника и при этом пользоваться всеми плюшками
Павел
Все эти каскады и орфаны приведут к тому что через пол года никто не поймет что происходит там
Просто эти штуки не должны быть критичными если их ставить. Это всего лишь сахар над ручным удалением через em. Про неявность тоже вопросы большие. В большом проекте вообще будут ивенты туда сюда летать через шину и будут удалять или что то делать вообще разные команды. Никто не будет явно из одного конекста удалять цепочку сущностей в другом, тем более синхронно. Мы на то и используем инструменты, чтобы сахарок использовать и скорость. Например сама доктрина одна сплошная неявность. Лучше ходить в БД напрямую (хотя вроде как интерпрайз к этому и приходит, но нет смысла тянуть то, что полезно там, может быть не полезно здесь)
Alexey Mishurovskiy
Всем привет! вопрос по мессендеру.
Alexey Mishurovskiy
проблема с кроликом. консюмеры запущены, супервизор работает, но в какой то момет просто перестает разгребаться очередь
Alexey Mishurovskiy
переехал на новую инфру, и не понятно почему так. на старой все работало корректно.. а главное я не понимаю как проверить
Павел
проблема с кроликом. консюмеры запущены, супервизор работает, но в какой то момет просто перестает разгребаться очередь
Проверить работают ли консюмеры, проверить утечку памяти, залогировать вдоль и поперек по этапам хэндлер, чтобы понять, что именно лочит.
Dmitry
переехал на новую инфру, и не понятно почему так. на старой все работало корректно.. а главное я не понимаю как проверить
вручную заходи в контейнер, запускай консьюмеры параллельно открывай админку рэббита и вручную попробуй отправить сообщение возможно DSN не перенесли до конца
Alexey Mishurovskiy
Виктор
Всем привет! Нормально вообще так делать? interface CommentableInterface { ... } class Album implements CommentableInterface { ... } class Photo implements CommentableInterface { ... } interface CommentInterface { ... public function setParent(?CommentableInterface $parent): static; ... } abstract class Comment implements CommentInterface { ... } class AlbumComment extends Comment { ... public function setParent(?CommentableInterface $parent): static { if (!is_a($parent, Album:class)) throw new Exception(); ... } ... } class PhotoComment implements Comment { ... public function setParent(?CommentableInterface $parent): static { if (!is_a($parent, Photo:class)) throw new Exception(); ... } ... }
Павел
выглядит не очень. Только если ну очень нужна обезличенность и абстракция.
Виктор
У меня есть методы, которые принимают в качестве аргумента AlbumComment и PhotoComment. Сейчас там юнион этих двух, но мне это кажется неправильным. Хочу описать интерфейс для комментариев и заменить юнион на него. Но как тогда описать метод, который устанавливает родителя?
Виктор
выглядит не очень. Только если ну очень нужна обезличенность и абстракция.
Да это скорее по-приколу) Хочу понять, как такое решается.
Павел
У меня есть методы, которые принимают в качестве аргумента AlbumComment и PhotoComment. Сейчас там юнион этих двух, но мне это кажется неправильным. Хочу описать интерфейс для комментариев и заменить юнион на него. Но как тогда описать метод, который устанавливает родителя?
В этом констексте звучит чуть более логичнее, но возможно стоит рассмотреть просто разделение метов или еще что. Потому что по факту вы знаете с чем вы работает, и что нужно туда подсовывать
Павел
В общем наверное приемлемо, но не очень.
Павел
У меня есть методы, которые принимают в качестве аргумента AlbumComment и PhotoComment. Сейчас там юнион этих двух, но мне это кажется неправильным. Хочу описать интерфейс для комментариев и заменить юнион на него. Но как тогда описать метод, который устанавливает родителя?
Но опять же, возможно стоит рассмотреть разделение методов и уход от абстракции. Вы сначала разделиои коммент на 2 сущности, а теперь пытаетесь их объединить к одному флоу видимо.
Павел
Т.е. имхо или не разделять комменты, или же не объединять потом флоу, раз они все же разные
Павел
Потому что контракт public function setParent(?CommentableInterface $parent) - который по итогу работает только с 1 имплементацией которая нигде не видна снаружи - это плохой контракт.
Nikolay
В некоторых случаях всякие сеттеры сигнализируют, что объекты не нужны (у класса нет логики), и проще через просто запрос делать
Павел
В некоторых случаях всякие сеттеры сигнализируют, что объекты не нужны (у класса нет логики), и проще через просто запрос делать
Это да. Но через ОРМ просто удобнее, да и с ОРМ свернуть в raw sql, это как бы шаг вперед, до которого надо дойти)
Павел
Просто по началу кажется что это снова шаг назад, ведь есть божественные ОРМ)
Nikolay
Это да. Но через ОРМ просто удобнее, да и с ОРМ свернуть в raw sql, это как бы шаг вперед, до которого надо дойти)
Проблема в том, что уже вкорячено все это и попробуй переделать. Как я вижу работу с ОРМ: 1 уровень - Осмысленные методы (без сеттеров) 2 уровень - переход на сырые запросы там, где это можно сделать (insert ... update)
Виктор
Но опять же, возможно стоит рассмотреть разделение методов и уход от абстракции. Вы сначала разделиои коммент на 2 сущности, а теперь пытаетесь их объединить к одному флоу видимо.
Там разделение было вызвано тем, что разные сущности могут иметь комментарии, а привязывал их я с помощью дискриминатора. Вот и получается, что это единственная причина разделения комментария на отдельные классы. А по сути они одинаковые. Всё из абстрактного Comment, и только get/setParent разный.
Павел
Проблема в том, что уже вкорячено все это и попробуй переделать. Как я вижу работу с ОРМ: 1 уровень - Осмысленные методы (без сеттеров) 2 уровень - переход на сырые запросы там, где это можно сделать (insert ... update)
Ну анемик тоже имеет место быть. Т.е. если есть инструмент комфортный, почему бы его не импользовать. Raw писать не быстрее, чтобы это был прям тру вэй во всех случаях где нет логики. Поддерживать связи, грязные пропсы, зачем если это есть в ОРМ.
Nikolay
Можно через абстрактный класс сделать, но стоит ли так
Павел
С комментами вообще всегда дилема: разделять ли их на сущности/таблицы или нет. Или проще сделать 1 сущность коммент, а для оптимизации какие нить партиции или еще что
Павел
@viozh Т.е. вы могли в целом сделать unidirectional many to many связь и управление только на строне album, photo . Тогда не пришлось бы на стороне comment городить setParent и делать разные albumComment PhotoComment
Виктор
Да, вы мне так и советовали)) Но я захотел через дискриминаторы, потому что с ними не был знаком.
Виктор
И в принципе я ни о чём не жалею - теперь познакомился)
Виктор
Но Album, Photo же не через дескриминатор. И получается их все равно достаете конкретно, а не абстрактно? $album = $albumRepo->get($albumId) $comment->setParent($album) Как вы $album абстрагируете?
Ну вот я как раз хотел сделать CommentableInterface, который имплементить во всех сущностях, которые можно комментировать. И уткнулся в то, с чего начал этот тред - как быть с setParent.