управление однородными, но разными сущностями (STI)

Koc

Новичок
Есть комментарии к: топику, торговой марке, встрече, фотке встречи, месту, пользователю. Все это хранится в одной таблице, используется паттерн STI. Операции, производимые над комментариями в общем-то одинаковые - CRUD, без U.

Но есть отличия:
1) в целом комментарий может удалять владелец комментируемого объекта или автор комментария, при условии, что на коммент не поступало ответа. Но у торговых марок нет автора, стало быть условие несколько другое. Причем проверять это условие нужно не только перед удалением, но и при рендеринге - что б лишний раз не показывать кнопку
2) после создания/удаления комментария будут происходить разные действия. Где-то нужно обновить информацию у родительского объекта, где-то нужно кого-то подписать (новостная лента) на объект, или опубликовать новость в ленту. При этом комментарии к встрече и топику будут вещать на разные каналы. Более того, топики бывают разных видов: топик района, топик группы, общий топик - здесь тоже могут быть разные каналы. А еще нужно отправлять письмо со ссылкой на комментируемый объект - для этого могут понадобиться какие-то дополнительные данные - подргузить группу/район/фотку и саму встречу.
3) понятное дело вывод может быть разным

Как бы напрашивается стратегия, но не получается ее реализовать в данном контексте. Слишком много всего. Что посоветуете?
 

Mols

Новичок
Делал что-то подобное.
В общем каждая сущность имела методы вида.
PHP:
->getUrl($mode=SELF,$params=array()) // mode= SELF | EDIT | DELETE  - если SELF - то ссылка на объект
->isEditAvailable()
->isRemoveAvailable()
->getAuthor()
->getParent()
Где нужно они переопределялись.
Был шаблон с управляющими действиями (панелька управления со ссылками "удалить", "редактировать"), который принимал объект и проверял показывать ли ссылки на редактирование, удаление. Ну и понятное дело, сам шаблон можно было подключать в другие шаблоны....
Это решало часть задач описанных выше.
По поводу подписать/отписать - похоже на паттерн наблюдатель.

З.Ы.
Этот набор (кроме getParent) был в общем-то у каждой сущности. То есть у объектов к которым цеплялись комменты, тоже можно было запросить автора или URL.
 

Koc

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

getUrl() - для этого я должен инъектить в сущность роутер
isRemoveAvailable() - тут - секьюрити контекст, что б понять, под кем мы залогинились.

По поводу подписать/отписать - похоже на паттерн наблюдатель.
да, там events+event dispatcher. Вопрос в том - генерировать для всех случаев одно событие

PHP:
$comment = new TopicComment();
$event = new CommentCreation($comment)
$dispatcher->dispatch('comments.creation', $event);

$comment = new PhotoComment();
$event = new CommentCreation($comment)
$dispatcher->dispatch('comments.creation', $event);

или разные

PHP:
$comment = new TopicComment();
$event = new CommentCreation($comment)
$dispatcher->dispatch('topics.comments.creation', $event);

$comment = new PhotoComment();
$event = new CommentCreation($comment)
$dispatcher->dispatch('photos.comments.creation', $event);
+ если еще учесть, что топики бывают разные - DistrictTopic, SimpleTopic, StyleTopic - дробить на разные события или нет?
 

A1x

Новичок
дробить на разные события или нет?
я думаю что нет, если не ясно зачем это. Тем более что в event передается сам комент, по которому можно узнать его тип
так можно ничего не начать писать если пытаться все предугадать (это мне знакомо) или получится что-то вроде магенты ;-)

прямо в сущности такие методы думаю лучше не размещать. Это ж нарушение SRP.
вот подумал, SRP это хорошо, но как тогда один класс может реализовать несколько интерфейсов?
 

Koc

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

PHP:
function handleCommentCreation(CommentCreation $event)
{
  if (!$event->getComment() instanceof PhotoComment) {
    return;
  }
}
 

Koc

Новичок
да, мы пробовали ее сделать, но она топорная получается
 

Mols

Новичок
Koc
Всё абсолютно верно))) Есть авторитетные мнения, что так лучше не делать. Сам долго колебался... сделал "посмотреть". Так и осталось ибо неудобств не вызвало.
Насчет событий я не зря сказал "похоже на паттерн".
У меня какое-то неприятие этого паттерна при программировании на PHP.
Приходится всех потенциальных слушателей создавать, что меня совсем не радует.
В общем забил я на него и сделал тупо в лоб.
Сервис при добавлении/удалении объекта делал всю нужную работу.
(Логику всегда можно сгруппировать в отдельных сервисах как удобно, ИМХО выходит вполне приемлемо)
Это не претендует на рекомендацию ))) Просто разговор поддержать)))
 
Сверху