Шаблон проектирования для построения временной шкалы, основанной на GitHub, с реляционной базой данных?

Существует ли шаблон дизайна для построения временной шкалы, основанной на GitHub? Я пытаюсь написать несколько сложную и универсальную систему временной шкалы для моего приложения. Он основан на этой концепции:

[Subject] [Verb] [DirectComplement] [IndirectComplement] (metadata: [date])

Итак, на практике:

John created a new post called Beautiful Post (12/01 00:01)

Джон - предмет, созданный глагол, "Прекрасная почта" является прямым дополнением.

John commented "OMG" on Beautiful Post  (12/01 00:00)

Джон - субъект, прокомментированный глагол: "OMG" является прямым дополнением, а Beautiful Post - косвенным дополнением.

Я работаю с Symfony2 и Doctrine, запустив MySQL. Я создал объект с именем Timeline, который хранит в качестве строки модель объекта Subject, DirectComplement и IndirectComplement, а также их идентификаторы. Затем, вручную, я делаю правильные запросы, чтобы получить объекты каждого из них.

Есть ли способ сделать это с помощью Doctrine и MySQL? Более элегантный и универсальный подход, который не делает меня сумасшедшим и заставляет меня делать абсурдное количество запросов и foreachs?

Ответ 1

О схеме базы данных

ActivityStrea.ms - это стандартное предложение для потоков социальной активности, подобных тому, которое вы хотите. Там много подобных сообщений здесь о SO в основном касаются проектирования баз данных этих потоков активности (ссылки в конце). Пожалуйста, не стоит недооценивать чтение ActivitySrea.ms JSON Schema. Я уверен, что вы многое узнаете от него.

Я предлагаю вам использовать этот проект базы данных:

user_id        |  INTEGER  |  user being notified
actor_id       |  INTEGER  |  user performing the action
activity_type  |  STRING   |  classname/type of the object being notified
activity_id    |  INTEGER  |  id of the object being notified
context_type   |  STRING   |  classname/type of the object parent
context_id     |  INTEGER  |  id of the object parent
read/view_at   |  DATETIME |  timestamp of when user saw it

Так, например, если кто-то комментирует сообщение, у вас будет что-то вроде:

$notification = array(
    'user_id'       => $id_of_the_user_being_notified
    'actor_id'      => $comment->user_id
    'activity_type' => 'comment'
    'activity_id'   => $comment->id
    'context_type'  => 'post'
    'context_id'    => $comment->post_id
    'read_at'       => NULL
);

Кажется излишним иметь все эти поля, но они, безусловно, будут платить за них.

С помощью этого дизайна вы можете:

  • Относящиеся к группе уведомления по пользователю, типу или контексту
  • Отфильтровать уведомления по типу действия, типу контекста и определенным субъектам (через объединение)
  • Легко очищать уведомления от удаляемых объектов (предположим, что пользователь удаляет сообщение, которое было прокомментировано. Уведомления о его комментариях должны исчезнуть)

Примечание. Временные метки (created_at/updated_at) на самом деле не нужны. Так как вы загрузите объект activity (запись комментария в этом случае), у вас будут свои метки времени. Единственной причиной их дублирования является запрос "уведомлений" по меткам времени (здесь вы не сможете использовать JOIN). В любом случае, не стесняйтесь добавлять их по своему усмотрению.

О Доктрине и Симфонии

Я не могу сказать много для Symfony, но я уверен, что Doctrine поддерживает полиморфные запросы. Имея это в виду, он должен хорошо играть с этим дизайном.

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

Приложение само прислушивается к методу модели create и генерирует уведомления, когда они подходят, поэтому модели и контроллеры не должны иметь дело с самими уведомлениями, прекрасно разделены, и изменение хранилища должно быть максимально простым.

Пример NotifiableInterface

Это довольно простой пример NotifiableInterface. Вы должны использовать его как вдохновение и адаптировать его в соответствии с вашими потребностями.

interface NotifiableInterface {

    // Returns a string representation of the type
    // It may be a get_class($this), the model table
    // or anything you like really.          
    public function get_type();

    // Returns an identifier for the object (ie its ID)
    // get_key is for compatibility with Laravel models
    // but you may use get_id.
    public function get_key();

    // Returns the context object for this entity.
    // It advisable that this object also implements
    // NotifiableInterface, so it also has get_type and get_key
    public function get_context();

    // Returns the user_ids to be notified.
    // A comment, for instance, should notify the post owner
    // as well as anyone else that commented that post.
    public function should_notify();

}

Вопросы, относящиеся

Вот несколько сообщений с обильной информацией по этой теме: