Доброго времени суток всем!
Часто возникает необходимость хранить данные логического типа для определенных таблиц. Например, таблица пользователей, такими данными могут быть поля активация пользователя, блокирование пользователя и др. Для таких полей удобно использовать битовую маску, при которой все данные хранятся в одном поле таблицы. Последнее время работаю с фреймверком 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 и экшн с базовыми средствами настройки.