|
|
@ -1,8 +1,8 @@ |
|
|
|
# status-combination 融合状态 |
|
|
|
# BitFlag 位标志 |
|
|
|
|
|
|
|
### Configuration |
|
|
|
|
|
|
|
##### 添加文件: `StatusBehavior.php` |
|
|
|
##### 添加文件: `BitFlagBehavior.php` |
|
|
|
|
|
|
|
```php |
|
|
|
<?php |
|
|
@ -12,18 +12,18 @@ use yii\base\Behavior; |
|
|
|
use yii\db\ActiveRecord; |
|
|
|
use yii\db\Expression; |
|
|
|
|
|
|
|
class StatusBehavior extends Behavior |
|
|
|
class BitFlagBehavior extends Behavior |
|
|
|
{ |
|
|
|
/** |
|
|
|
* [ |
|
|
|
* 融合属性 => [ |
|
|
|
* 状态位 => 状态名 |
|
|
|
* 位标志名 => [ |
|
|
|
* 标志位 => 标志名 |
|
|
|
* ] |
|
|
|
* ... |
|
|
|
* ] |
|
|
|
* @var array[] $statusAttributes 融合状态表 |
|
|
|
* @var array[] $bitFlags 位标志映射表 |
|
|
|
*/ |
|
|
|
public $statusAttributes = []; |
|
|
|
public $bitFlags = []; |
|
|
|
|
|
|
|
public function events() |
|
|
|
{ |
|
|
@ -36,62 +36,62 @@ class StatusBehavior extends Behavior |
|
|
|
|
|
|
|
public function beforeSave() |
|
|
|
{ |
|
|
|
foreach ($this->statusAttributes as $field => $attributes) { |
|
|
|
$this->owner->$field = 0; |
|
|
|
$this->setStatusCombination($field, $attributes); |
|
|
|
foreach ($this->bitFlags as $bitFlag => $flags) { |
|
|
|
$this->owner->$bitFlag = 0; |
|
|
|
$this->setBitFlag($bitFlag, $flags); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public function beforeUpdate() |
|
|
|
{ |
|
|
|
foreach ($this->statusAttributes as $field => $attributes) { |
|
|
|
$this->setStatusCombination($field, $attributes); |
|
|
|
foreach ($this->bitFlags as $bitFlag => $flags) { |
|
|
|
$this->setBitFlag($bitFlag, $flags); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public function afterFind() |
|
|
|
{ |
|
|
|
$owner = $this->owner; |
|
|
|
foreach ($this->statusAttributes as $field => $attributes) { |
|
|
|
$status = $owner->$field; |
|
|
|
foreach ($attributes as $pos => $attribute) { |
|
|
|
$owner->$attribute = ($status & 1 << $pos) >> $pos; |
|
|
|
foreach ($this->bitFlags as $bitFlag => $flags) { |
|
|
|
$bitFlagValue = $owner->$bitFlag; |
|
|
|
foreach ($flags as $pos => $flag) { |
|
|
|
$owner->$flag = ($bitFlagValue & 1 << $pos) >> $pos; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 设置融合字段 |
|
|
|
* @param string $field 融合字段名 |
|
|
|
* @param string[] $attributes 字段 |
|
|
|
* 设置位标志 |
|
|
|
* @param string $bitFlag 位标志 |
|
|
|
* @param string[] $flags 标志 |
|
|
|
*/ |
|
|
|
public function setStatusCombination($field, $attributes) |
|
|
|
public function setBitFlag($bitFlag, $flags) |
|
|
|
{ |
|
|
|
$owner = $this->owner; |
|
|
|
foreach ($attributes as $pos => $attribute) { |
|
|
|
$status = $owner->$attribute; |
|
|
|
if ($status === null) { |
|
|
|
foreach ($flags as $pos => $flag) { |
|
|
|
$flagValue = $owner->$flag; |
|
|
|
if ($flagValue === null) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
$owner->$field = $this->getUpdateStatusCombination($owner->$field, $pos, $status); |
|
|
|
$owner->$bitFlag = $this->getBitFlagUpdate($owner->$bitFlag, $pos, $flagValue); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获得更新后的融合状态 |
|
|
|
* @param int $statusCombination 融合状态 |
|
|
|
* 获得更新后的位标志值 |
|
|
|
* @param int $bitFlagValue 位标志值 |
|
|
|
* @param int $pos 状态位置 |
|
|
|
* @param bool|int $status 状态 |
|
|
|
* @param bool|int $flagValue 标志值 |
|
|
|
* @return int |
|
|
|
*/ |
|
|
|
public function getUpdateStatusCombination($statusCombination, $pos, $status) |
|
|
|
public function getBitFlagUpdate($bitFlagValue, $pos, $flagValue) |
|
|
|
{ |
|
|
|
if ($status) { |
|
|
|
$statusCombination = $statusCombination | 1 << $pos; |
|
|
|
if ($flagValue) { |
|
|
|
$bitFlagValue = $bitFlagValue | 1 << $pos; |
|
|
|
} else { |
|
|
|
$statusCombination = $statusCombination & ~(1 << $pos); |
|
|
|
$bitFlagValue = $bitFlagValue & ~(1 << $pos); |
|
|
|
} |
|
|
|
return $statusCombination; |
|
|
|
return $bitFlagValue; |
|
|
|
} |
|
|
|
} |
|
|
|
``` |
|
|
@ -102,7 +102,7 @@ class StatusBehavior extends Behavior |
|
|
|
|
|
|
|
namespace {yourApp}\models; |
|
|
|
|
|
|
|
use {yourApp}\behaviors\StatusBehavior; |
|
|
|
use {yourApp}\behaviors\BitFlagBehavior; |
|
|
|
|
|
|
|
class MyModel extends base\MyModel |
|
|
|
{ |
|
|
@ -119,15 +119,15 @@ class MyModel extends base\MyModel |
|
|
|
public $s8; |
|
|
|
|
|
|
|
/** |
|
|
|
* 融合状态表: |
|
|
|
* 位标志映射表: |
|
|
|
* [ |
|
|
|
* 融合属性 => [ |
|
|
|
* 状态位 => 状态名 |
|
|
|
* 位标志名 => [ |
|
|
|
* 标志位 => 标志名 |
|
|
|
* ] |
|
|
|
* ... |
|
|
|
* ] |
|
|
|
*/ |
|
|
|
const STATUS_ATTRIBUTES = [ |
|
|
|
const BIT_FLAGS = [ |
|
|
|
'status' => [ |
|
|
|
's0', |
|
|
|
's1', |
|
|
@ -146,9 +146,9 @@ class MyModel extends base\MyModel |
|
|
|
return [ |
|
|
|
// 其他Behavior |
|
|
|
|
|
|
|
'statusBehavior' => [ |
|
|
|
'class' => StatusBehavior::class, |
|
|
|
'statusAttributes' => self::STATUS_ATTRIBUTES, |
|
|
|
'bitFlagBehavior' => [ |
|
|
|
'class' => BitFlagBehavior::class, |
|
|
|
'bitFlags' => self::BIT_FLAGS, |
|
|
|
], |
|
|
|
]; |
|
|
|
} |
|
|
@ -159,7 +159,7 @@ class MyModel extends base\MyModel |
|
|
|
*/ |
|
|
|
public static function find() |
|
|
|
{ |
|
|
|
$config = ['statusAttributes' => self::STATUS_ATTRIBUTES]; |
|
|
|
$config = ['bitFlags' => self::BIT_FLAGS]; |
|
|
|
return new MyModelQuery(get_called_class(), $config); |
|
|
|
} |
|
|
|
} |
|
|
@ -178,53 +178,53 @@ class MyModelQuery extends ActiveQuery |
|
|
|
{ |
|
|
|
/** |
|
|
|
* [ |
|
|
|
* 融合属性 => [ |
|
|
|
* 状态位 => 状态名 |
|
|
|
* 位标志名 => [ |
|
|
|
* 标志位 => 标志名 |
|
|
|
* ] |
|
|
|
* ... |
|
|
|
* ] |
|
|
|
* @var array[] $statusAttributes 融合状态表 |
|
|
|
* @var array[] $bitFlags 融合状态表 |
|
|
|
*/ |
|
|
|
public $statusAttributes; |
|
|
|
public $bitFlags; |
|
|
|
|
|
|
|
/** |
|
|
|
* @param string[] $queryParams |
|
|
|
* @param string[] $conditions |
|
|
|
* @return MyModelQuery |
|
|
|
*/ |
|
|
|
public function andWhereStatus($queryParams = []) |
|
|
|
public function andWhereBitFlags($conditions = []) |
|
|
|
{ |
|
|
|
return $this->andWhere($this->getStatusCondition($queryParams)); |
|
|
|
return $this->andWhere($this->getBitFlagsCondition($conditions)); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @param string[] $queryParams |
|
|
|
* @param string[] $conditions |
|
|
|
* @return MyModelQuery |
|
|
|
*/ |
|
|
|
public function orWhereStatus($queryParams = []) |
|
|
|
public function orWhereBitFlags($conditions = []) |
|
|
|
{ |
|
|
|
return $this->orWhere($this->getStatusCondition($queryParams)); |
|
|
|
return $this->orWhere($this->getBitFlagsCondition($conditions)); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @param array $queryParams |
|
|
|
* @param array $conditions |
|
|
|
* @return Expression |
|
|
|
*/ |
|
|
|
public function getStatusCondition($queryParams = []) |
|
|
|
public function getBitFlagsCondition($conditions = []) |
|
|
|
{ |
|
|
|
$queryAttributes = array_keys($queryParams); |
|
|
|
foreach ($this->statusAttributes as $field => $attributes) { |
|
|
|
$conditionsKeys = array_keys($conditions); |
|
|
|
foreach ($this->bitFlags as $bitFlag => $flags) { |
|
|
|
$mask = $res = 0; |
|
|
|
foreach ($attributes as $pos => $attribute) { |
|
|
|
if (in_array($attribute, $queryAttributes)) { |
|
|
|
foreach ($flags as $pos => $flag) { |
|
|
|
if (in_array($flag, $conditionsKeys)) { |
|
|
|
$mask += 1 << $pos; |
|
|
|
$res += $queryParams[$attribute] << $pos; |
|
|
|
$res += $conditions[$flag] << $pos; |
|
|
|
} |
|
|
|
} |
|
|
|
if ($mask != 0) { |
|
|
|
$conditions[] = "$field & $mask = $res"; |
|
|
|
$bitFlagsConditions[] = "$bitFlag & $mask = $res"; |
|
|
|
} |
|
|
|
} |
|
|
|
return new Expression(implode('and', $conditions)); |
|
|
|
return new Expression(implode('and', $bitFlagsConditions)); |
|
|
|
} |
|
|
|
} |
|
|
|
``` |
|
|
@ -235,7 +235,7 @@ class MyModelQuery extends ActiveQuery |
|
|
|
|
|
|
|
```php |
|
|
|
$myModels = MyModel::find() |
|
|
|
->andWhereStatus(['s0' => 1, 's1' => 0]) |
|
|
|
->orWhereStatus(['s2' => 0, 's3' => 1]) |
|
|
|
->andWhereBitFlags(['s0' => 1, 's1' => 0]) |
|
|
|
->orWhereBitFlags(['s2' => 0, 's3' => 1]) |
|
|
|
->all(); |
|
|
|
``` |