Доброго времени суток всем!
Часто возникает необходимость хранить данные логического типа для определенных таблиц. Например, таблица пользователей, такими данными могут быть поля активация пользователя, блокирование пользователя и др. Для таких полей удобно использовать битовую маску, при которой все данные хранятся в одном поле таблицы. Последнее время работаю с фреймверком Yii. Мне он нравится и во всем устраивает. Так вот, в процессе работы над несколькими проектами у меня появилось ряд наработок для работы с битовой маской под этот фреймверк.
Ими и хочу поделиться.
И так, создаем модель, наследуя от ActiveRecord:
Объявляем флаги. Для базового класса задаем флаг блокировки, который может быть использован для большинства моделей.
Значение константы соответствует н��меру бита. Если биты будут одинаковые, флаги будут перетираться.
Дальше пишем методы для работы с флагами:
Модели, которые должны работать с флагами делаем наследниками этого класса и добавляем в таблицу поле flags.
Теперь, например, чтобы проверить, заблокирована ли новость, можно выполнить:
или чтобы заблокировать новость:
или, например, чтобы отфильтровать незаблокированные новости:
В модель можно добавить столько флагов, сколько позволяет разрядность типа поля в базе данных.
Если материал оказался полезным, я буду рад опубликовать продолжение данной темы, рассказав о готовых средствах администрирования флагов через CgridView и экшн с базовыми средствами настройки.
Часто возникает необходимость хранить данные логического типа для определенных таблиц. Например, таблица пользователей, такими данными могут быть поля активация пользователя, блокирование пользователя и др. Для таких полей удобно использовать битовую маску, при которой все данные хранятся в одном поле таблицы. Последнее время работаю с фреймверком Yii. Мне он нравится и во всем устраивает. Так вот, в процессе работы над несколькими проектами у меня появилось ряд наработок для работы с битовой маской под этот фреймверк.
Ими и хочу поделиться.
И так, создаем модель, наследуя от ActiveRecord:
class BaseActiveRecordClass extends CactiveRecord
Объявляем флаги. Для базового класса задаем флаг блокировки, который может быть использован для большинства моделей.
const FLAG_MANAGE_BLOCKED=0; //флаг блокировки
Значение константы соответствует н��меру бита. Если биты будут одинаковые, флаги будут перетираться.
Дальше пишем методы для работы с флагами:
/*
* функция установки флага модели
*/
public function setFlag($idBit=0,$bit=1){
$bitFlags=1<<$idBit;
if($bit==0){
$this->flags=$this->flags&(~$bitFlags);
}else{
$this->flags=$this->flags|$bitFlags;
}
$this->save(true, array('flags'));
}
/*
* фунукция получения флага
*/
public function getFlag($idBit){
$flag=(int)$this->flags;
$flag=$flag>>$idBit;
if($flag>0)
$cBits=log($flag,2);
else $cBits=0;
$newFlag=$flag|1;
if($newFlag==$flag)
return 1;
else
return 0;
}
/*
* функция фильтрации по флагам в базе данных
* param $flags array список флагов для фильтрации
*/
public function addFlagCriteria($flags=array()){
$criteria=$this->getDbCriteria();
if(!empty($flags)){
foreach($flags as $bit => $flag){
if(is_array($flag)){
$operator=($flag['operator'])?$flag['operator']:"and";
$check=($flag['check'])?(bool)$flag['check']:1;
}else{
$operator="and";
$check=(bool)$flag;
}
$check=$check?"=":"<>";
$criteria->addCondition("(((t.flags>>".$bit.")|1)".$check."(t.flags>>".$bit."))", $operator);
}
}
return $this;
}
/*
* пример фильтрации в базе по флагам
* отфильтровывает незаблокированные сущности
*/
public function noBlock(){
return $this->addFlagCriteria(array(self::FLAG_MANAGE_BLOCKED=>0));
}
Модели, которые должны работать с флагами делаем наследниками этого класса и добавляем в таблицу поле flags.
Теперь, например, чтобы проверить, заблокирована ли новость, можно выполнить:
$model= News::model()->findByPk($id);
if($model->getFlag(News::FLAG_MANAGE_BLOCKED)){
die("Новость заблокирована");
}
или чтобы заблокировать новость:
$model->setFlag(News::FLAG_MANAGE_BLOCKED, 1);
или, например, чтобы отфильтровать незаблокированные новости:
$news=News::model()->noBlock()->findAll();
В модель можно добавить столько флагов, сколько позволяет разрядность типа поля в базе данных.
Если материал оказался полезным, я буду рад опубликовать продолжение данной темы, рассказав о готовых средствах администрирования флагов через CgridView и экшн с базовыми средствами настройки.