Вопрос По Улучшайзингу

у меня есть таблица Stream, которая в себе агрегирует посты с соц. сетей.

Есть так же свои собственные сущности типа новости/аудио/видео/фото постов

которые представлены в виде отдельных таблиц, но с небольшой денормализирующей линковокой в таблице Stream

в каждой из этих таблиц есть поле статуса (показывать или не показывать пост)

вот возникла задача синхронизировать статус поста. Те если выключат пост в Stream, то зеркально надо выключить и прилинкованный пост в новости/аудио/видео/фото. Так же и надо изменить состояние в таблице Stream, если изменилось состояние в какой-то связанной таблице.

делать изменение статуса всех связанных таблиц в одной модели мне кажется не верным и совершенно кривым.

делать это путем выполнения в контролере серии методов из моделей вроде как лучше, но все равно мне это решение не нравится

в каком-то контролере можно упустить обновление в какой-нибудь модели.

в общем прошу совета как лучше и правильней организовать обновление статуса в нескольких таблицах

P.S.: всплывает идея использовать события, но я как-то не очень вкурил как они в Yii работают.

Спасибо

Триггером в БД.

В коде держать такие вещи смысла нет. Пусть это делает база данных. Напишите хранимую процедуру и вызывайте ее триггером по событию - ON UPDATE. В процедуре следует сверять изменилось ли состояние status, чтобы лишний раз не обновлять записи.

Это тоже вариант, но в принципе что в пхп будет код по обновлению, что в базе.

не хотелось бы такую задачу переносить в базу.

Вообще такие штуки делаются триггерами в БД.

В случае Yii - лучше это делать действительно в модели (только помнить, что AR-события не во всех случаях срабатывают). Это вполне ок, учитывая тот факт, что данные внезапно могут быть модифицированы не только из одного контроллера. Ну, например, дополнительное API какое-нибудь потребуется - и трындец. А так меньше логики таскать придется в случае чего.

Плюс ко всему прочему если в каждой модели повесить обработчик afterUpdate, к примеру, то можно выстраивать мощные цепочки типа обновилась модель - сработал обработчик, пнул связанную модель, сработал уже ее обработчик итд.

PS. В Yii2, кстати, уже из коробки идут oldAttributes, что позволяет без лишних телодвижений проверять изменение конкретного поля.

правильно ли я понимаю, что из одной модели таки прийдется дергать другую ?

или как вообще это все выстраивается ?

я пока себе вижу это как




class Stream extends CActiveRecord

{

    public function afterUpdate()

    {

        if (parent::afterUpdate())

        {

            if($true_logic) {

                News::model()->myMagicMethod();

            }

            return true;

        } 

        else

            return false;

    }


}



или есть какие-то более верные решения ?

Нууу, зависит.

Я в таких случаях всегда думаю примерно так: а что будет, если БД может модифицироваться не только из одного скрипта?

И выходит, что либо всю работу с БД придется протаскивать через какое-то Yii-api, либо перевесить логику на БД и успешно сохранять консистентность при любых обстоятельствах. Хоть через вебинтерфейс работа идет, хоть из перлового скрипта, хоть через консоль БД: данные всегда находятся в нужном состоянии.

хм, хорошая мысль. это действительно более гибкое решение

задумался, спасибо!

Не вижу в этом ничего плохого. Если между моделями есть связь - это нормально.

Да, я примерно так и делаю.

у меня какое-то внутреннее недовольство от такого способа. даже если они связаны логически.

если надо делать такие вещи, то я пишу хелпер и переношу его запуск в контролер

Вот поэтому и триггеры :)

Ну, если есть возможность писать свою БД-логику.

По личному опыту - триггеры в БД лучше событий AR.

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

Если честно сам поначалу боялся что тяжело и так далее, а на самом деле оказалось намного проще, ну и еще + выигрыш в производительности (по сравнению с тем же AR).

Некоторые методы, типа updateAll/deleteAll принципиально не вызывают событий, просто sql сразу отправляют на исполнение. Ну, логично.

Впрочем, с БД-триггерами хорошо только там, где хранимая логика нормально поддерживается. В постгресе, например.

к примеру есть такие таблицы Table1 и Table2

В table1 есть внешний ключ с on delete cascade к полю в таблице Table2

тогда удаляя запись в Table1, то в Table2 события не сработают.

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

Как сделали в итоге?

пока курю тригеры, но что-то через pma они у меня не идут

Sasha, если у вас намечается сложная цепочка зависимостей моделей со статусами - то рекомендую попробовать плагин "simpleWorkflow": www.yiiframework.com/extension/simpleworkflow

Подробное описание здесь: http://s172418307.onlinehome.fr/project/yiiDemo/index.php?r=simpleworkflowdemo/index

Поддерживает маршруты статусов, позволяет задавать условия и триггеры при переходе "из статуса Х" или "в статус Х".

Мне хорошо помог навести порядок в зависимостях моделей, использующих статус.

спасибо, посмотрю !