Лента событий. Как лучше реализовать?

Всем привет :) . Делаю проект очень похожий на гуглокод. Начал делать ленту событий и возникли некоторые вопросы/проблемы. Есть таблица Timeline в которую записываются все изменения - новый коммент, баг; основные поля - название модели и id записи. В каждой модели есть метод timelineFragment, который формирует соответствующее отображение. Допустим на одной странице ленты будет 50 событий. 1 запрос - извлечь из ленты 50 записей. И далее возможные варианты:

  1. мне нужно создать 50 экземпляров моделей (=50 запросов), вызвать у каждой timelineFragment и передать во вьюху;

  2. создать в Timeline поле, которое хранит сериализованный объект модели. Потом просто десериализовывать, вызывать timelineFragment и передавать во вьюху;

  3. мудрить с кэшем - но подробно еще не прорабатывал этот вариант.

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

Во-первых, почему отображение формируется моделью? Это как-то не в духе MVC.

Во-вторых, раз лента общая для нескольких моделей, то и её "ячейки" должны быть унифицированы? Т.е. в таблице Timeline имеем, к примеру, поля для заголовка, "тела" сообщения, времени и т.п. После сохранения конкретной модели в таблицу Timeline должна добавиться соответствующая запись. Наиболее логично реализовать это в виде поведения (CActiveRecordBehavior), который можно прицепить к любой модели.

Поправьте, если я ошибаюсь во втором пункте.

  1. Согласен, но пока это самое быстрое решение. Над этим еще буду думать.

  2. Структуру определил такую.

id int(11) NOT NULL AUTO_INCREMENT,

project_id int(11) NOT NULL,

user_id int(11) NOT NULL,

model_class varchar(150) NOT NULL,

model_id int(11) NOT NULL,

added_on datetime DEFAULT NULL,

created_on datetime DEFAULT NULL,

"Тело сообщения" я формирую в timelineFragment при вызове действия контроллера, так как не всё унифицировано: если это коммит, то показывается: Commit Message - Commit 29d966cdb3178963702a87919ad3e4ae496e510c, by USER;

если это создание тикета, то Creation of issue ### by USER;

если коммент, то Comment on issue ###, by User, Status: ###, Owner: USER;

А вы предлагаете, при вставке какой либо записи формировать сообщение и вставлять в Timeline? Тогда в какой виде лучше вставлять: сразу оформленное для вывода в view, или допустим массива?

Я думаю, что проще будет хранить всю необходимую информацию в одной таблице, и не стоит вставлять сразу оформленное сообщение. Это не есть хорошо ни с точки зрения расширяемости, ни с точки зрения экономии дискового пространства :)

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

Немного не понял. От одной модели мне допустим нужны 3 определенных поля, от другой только 2 других. Как в одной таблице хранить?

Для всех полей моделей создать одно поле в таблице Timeline (напр. "params"). Пусть это будет сериализованный массив. В afterSave() каждой модели происходит запись в таблицу Timeline. При извлечении записей из таблицы Timeline происходит отображение того или иного представления (в зависимости от model_class), в которое передаются те самые params.

Подход конечно не в духе реляционной модели, но и структура таблицы Timeline тоже далеко не в этом же духе :) Зато, как говорится, “дешево и сердито”.

Ага, в общем-то я подобное делал.

$project = $this->project;

$timelines = Timeline::model()->with(‘user’)->findAllByAttributes(array(‘project_id’ => $project->id));

foreach ($timelines as $timeline)

{

 $model = unserialize($timeline->content);


 $out = $model->timelineFragment($project);


 dump($out);

}

Но думаю целый объект хранить не экономично, лучше в массивы заталкивать нужные поля. Спасибо :)

Само собой, сохранять следует только нужные поля, потому что ненужные поля не нужны :lol: А от рендеринга представления моделью всё-таки избавляйтесь…