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

  • Автор темы Автор темы Koc
  • Дата начала Дата начала

Koc

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

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

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

З.Ы.
Этот набор (кроме getParent) был в общем-то у каждой сущности. То есть у объектов к которым цеплялись комменты, тоже можно было запросить автора или URL.
 
прямо в сущности такие методы думаю лучше не размещать. Это ж нарушение 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 - дробить на разные события или нет?
 
дробить на разные события или нет?
я думаю что нет, если не ясно зачем это. Тем более что в event передается сам комент, по которому можно узнать его тип
так можно ничего не начать писать если пытаться все предугадать (это мне знакомо) или получится что-то вроде магенты ;-)

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

PHP:
function handleCommentCreation(CommentCreation $event)
{
  if (!$event->getComment() instanceof PhotoComment) {
    return;
  }
}
 
да, мы пробовали ее сделать, но она топорная получается
 
Koc
Всё абсолютно верно))) Есть авторитетные мнения, что так лучше не делать. Сам долго колебался... сделал "посмотреть". Так и осталось ибо неудобств не вызвало.
Насчет событий я не зря сказал "похоже на паттерн".
У меня какое-то неприятие этого паттерна при программировании на PHP.
Приходится всех потенциальных слушателей создавать, что меня совсем не радует.
В общем забил я на него и сделал тупо в лоб.
Сервис при добавлении/удалении объекта делал всю нужную работу.
(Логику всегда можно сгруппировать в отдельных сервисах как удобно, ИМХО выходит вполне приемлемо)
Это не претендует на рекомендацию ))) Просто разговор поддержать)))
 
Сверху