ECountableBehavior

Выкладываем свои наработки
Ответить
mitallast
Сообщения: 207
Зарегистрирован: 2010.02.21, 20:40
Откуда: Голицыно
Контактная информация:

ECountableBehavior

Сообщение mitallast »

Привет!

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

Рассмотрим, как оно действует в текущей версии:
У нас есть модели Post и Section. Связь между моделями : Post BELONGS_TO Section. У Section есть поле post_count, которое должно хранить количество моделей Post.
Описываем Post :

Код: Выделить всё

public function behaviors(){        
    return array(                
        'blog_counter' => array(
            'class' => 'application.extentions.countable.ECountableBehavior',
            'model' => 'Section',
            'modelCounter' => 'post_counter',
            'modelFk' => 'section_id',
        ),
    );
} 
Теперь, при изменении модели Post (добавлении, обновлении и т.п) будет изменяться значение Section.post_counter.
Если у Post поменяли Section, то после сохранения изменения счетчики обновятся и у старой Section , и у новой.

Если нужно учитывать некоторые правила, модель можно валидировать - для этого нужно добавить свойство (string) scenario, по которому выполнится Post->validate(), например:

Код: Выделить всё

function rules(){
    return array(
        array('status', 'compare' , 'compareValue' => self::status_published, 'on' => 'section_count_update')
    );
}

function behaviors(){
    return array(                
        'blog_counter' => array(
            'class' => 'application.extentions.countable.ECountableBehavior',
            'model' => 'Section',
            'modelCounter' => 'post_counter',
            'modelFk' => 'section_id',
            'scenario' => 'section_count_update',
        ),
    );
}
 
В планах:
  • возможность апдейта, который запрашивает в базе общее количество моделей во избежание ошибок, а не инкрементит текущее значение
  • работа с многоколоночным первичным ключом
  • поддержка привязки как к таблице\модели , так и CActiveRecord
Вложения
ECountableBehavior.zip
(2.24 КБ) 220 скачиваний
nagash
Сообщения: 35
Зарегистрирован: 2010.03.30, 14:26
Откуда: Украина, г. Сумы

Re: ECountableBehavior

Сообщение nagash »

сори за оффтоп, но почему обновление счетчиков не поручить триггерам?
mitallast
Сообщения: 207
Зарегистрирован: 2010.02.21, 20:40
Откуда: Голицыно
Контактная информация:

Re: ECountableBehavior

Сообщение mitallast »

И в самом деле, почему :(
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: ECountableBehavior

Сообщение samdark »

Например, потому, что используется SQLite.
mitallast
Сообщения: 207
Зарегистрирован: 2010.02.21, 20:40
Откуда: Голицыно
Контактная информация:

Re: ECountableBehavior

Сообщение mitallast »

C sqlite почти не работал, хотя тоже в голову пришло, но
http://www.sqlite.org/lang_createtrigger.html

Попробовал написать триггеры, получилось типа такого

Код: Выделить всё

CREATE TRIGGER post_count_up AFTER UPDATE ON post
FOR EACH ROW BEGIN
    IF OLD.section_id != NEW.section_id THEN
    UPDATE section set section.post_count = section.post_count - 1 where section.id = OLD.section_id;
    UPDATE section set section.post_count = section.post_count + 1 where section.id = NEW.section_id;
    END IF
END


CREATE TRIGGER post_count_ins AFTER INSERT ON post
FOR EACH ROW
    UPDATE section SET section.post_count = section.post_count + 1 WHERE section.id = NEW.section_id

CREATE TRIGGER post_count_del AFTER DELETE ON post
FOR EACH ROW
    UPDATE section SET section.post_count = section.post_count - 1 WHERE section.id = OLD.section_id
Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: ECountableBehavior

Сообщение slavcodev »

mitallast писал(а):CStatRelation не удовлетворил меня своим функционалом - в часности, такой нужной вещью, как сортировка
Можно уточнить, что значит не удовлетворил с сортировкой?
Жду Yii 3!
mitallast
Сообщения: 207
Зарегистрирован: 2010.02.21, 20:40
Откуда: Голицыно
Контактная информация:

Re: ECountableBehavior

Сообщение mitallast »

СStatRelation не поддерживает джойн к основной таблице, вследствие чего невозможно отсортировать\отобрать данные из основной таблицы по агрегированному значению.

Другими словами, CStatRelation происходит отдельным запросом , со всеми вытекающими ограничениями
Сообщник
Сообщения: 14
Зарегистрирован: 2011.01.19, 13:47

Re: ECountableBehavior

Сообщение Сообщник »

nagash писал(а):сори за оффтоп, но почему обновление счетчиков не поручить триггерам?
Тригеры размывают логику, особенно если они связанны со счётчиками.
mitallast
Сообщения: 207
Зарегистрирован: 2010.02.21, 20:40
Откуда: Голицыно
Контактная информация:

Re: ECountableBehavior

Сообщение mitallast »

Также триггеры не помогут при шардинге, логическом разнесении данных и вообще хайлоаде. Также будут проблемы при переходе с одной БД на другую.

К тому же StatRelation теперь отношусь как к бесполезной вещи на нагруженном сайте.

Однако, как меняются взгляды по прошествии времени =)
Сообщник
Сообщения: 14
Зарегистрирован: 2011.01.19, 13:47

Re: ECountableBehavior

Сообщение Сообщник »

Однако, как меняются взгляды по прошествии времени =)
Это опыт так влияет =)
theKiller
Сообщения: 153
Зарегистрирован: 2010.02.28, 22:58

Re: ECountableBehavior

Сообщение theKiller »

Триггеры конечно здорово, но очень уж они не доработаны.
Пример, в случае релейшена в рамках одной таблицы (например по parentId) триггер выдаст ошибку. Еще пример, если данные удаляются релейшенами, то по таким удалениям триггеры подчиненных таблиц не сработают.

Так что делать часть через триггеры, часть в скриптах как то не правильно на мой взгляд.

З.Ы. речь про MySQL.
mitallast
Сообщения: 207
Зарегистрирован: 2010.02.21, 20:40
Откуда: Голицыно
Контактная информация:

Re: ECountableBehavior

Сообщение mitallast »

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

Первый тип представляет из себя по сути интерфейс к БД, сущности по максимуму описаны в именно в БД , в том числе такие вещи как реляции, ограничения и т.п. Это нормальная практика, особенно для небольших проектов. В таком приложении частенько будут исполняться запросы с джойнами, денормализации данных почти нет. В итоге, логика выборок будет сложной, сильно связанной. Станет сложнее делать рефакторинг, логическое разнесение информации, шардинг и прочие средства увеличения производительности.

Второй тип - совершенно непохож на предыдущий. Внем вся логика поведения описана в коде приложения, бд используется практически как nosql. Данные практически полностью денормализованы, запросов типа select count(*) просто невозможно выполнить, вместо них - счетчики. За счет этого БД можно разбивать, и соответственно проще выполнять масштабирование.
Ответить