📜 ⬆️ ⬇️

Work with bit mask

Good day to all!
It is often necessary to store data of a logical type for certain tables. For example, a user table, such data may be user activation fields, user blocking, etc. For such fields it is convenient to use a bit mask, in which all data is stored in one field of the table. Recently I have been working with the framework Yii. I like it and in everything suits. So, in the process of working on several projects, I had a number of developments for working with the bit mask for this framework.
I want to share them.

And so, we create a model, inheriting from ActiveRecord:

class BaseActiveRecordClass extends CactiveRecord 


We declare flags. For the base class, we set the lock flag, which can be used for most models.
')
 const FLAG_MANAGE_BLOCKED=0; //  


The constant value corresponds to the bit number. If the bits are the same, the flags will be ground.
Further we write methods for working with flags:

 /* *     */ 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)); } 


Models that should work with flags are made by the heirs of this class and add the flags field to the table.
Now, for example, to check whether the news is blocked, you can run:

 $model= News::model()->findByPk($id); if($model->getFlag(News::FLAG_MANAGE_BLOCKED)){ die(" "); } 

or to block the news:
 $model->setFlag(News::FLAG_MANAGE_BLOCKED, 1); 


or, for example, to filter unblocked news:
 $news=News::model()->noBlock()->findAll(); 


You can add as many flags to the model as the bitness of the field type in the database allows.

If the material turned out to be useful, I will be glad to publish a continuation of this topic, talking about the ready means of administering flags via CgridView and an action with basic configuration tools.

Source: https://habr.com/ru/post/130427/


All Articles