commit 9aad868b46dce9c34c53aee78de2a25a2c5d8378 Author: LIERLIER <1113093541@qq.com> Date: Thu Aug 17 10:17:49 2023 +0800 readme diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..0b443bf --- /dev/null +++ b/readme.md @@ -0,0 +1,241 @@ +# status-combination 融合状态 + +### Configuration + +##### 添加文件: `StatusBehavior.php` + +```php + [ + * 状态位 => 状态名 + * ] + * ... + * ] + * @var array[] $statusAttributes 融合状态表 + */ + public $statusAttributes = []; + + public function events() + { + return [ + ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave', + ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeUpdate', + ActiveRecord::EVENT_AFTER_FIND => 'afterFind', + ]; + } + + public function beforeSave() + { + foreach ($this->statusAttributes as $field => $attributes) { + $this->owner->$field = 0; + $this->setStatusCombination($field, $attributes); + } + } + + public function beforeUpdate() + { + foreach ($this->statusAttributes as $field => $attributes) { + $this->setStatusCombination($field, $attributes); + } + } + + 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; + } + } + } + + /** + * 设置融合字段 + * @param string $field 融合字段名 + * @param string[] $attributes 字段 + */ + public function setStatusCombination($field, $attributes) + { + $owner = $this->owner; + foreach ($attributes as $pos => $attribute) { + $status = $owner->$attribute; + if ($status === null) { + continue; + } + $owner->$field = $this->getUpdateStatusCombination($owner->$field, $pos, $status); + } + } + + /** + * 获得更新后的融合状态 + * @param int $statusCombination 融合状态 + * @param int $pos 状态位置 + * @param bool|int $status 状态 + * @return int + */ + public function getUpdateStatusCombination($statusCombination, $pos, $status) + { + if ($status) { + $statusCombination = $statusCombination | 1 << $pos; + } else { + $statusCombination = $statusCombination & ~(1 << $pos); + } + return $statusCombination; + } +} +``` + +##### 在需要的`Model`里添加`Behavior` +```php + [ + * 状态位 => 状态名 + * ] + * ... + * ] + */ + const STATUS_ATTRIBUTES = [ + 'status' => [ + 's0', + 's1', + 's2', + 's3', + ], + // 'flags' => [ + // 's5', 's6', 's7', 's8' + // ] + ]; + + // 其他Model代码...... + + public function behaviors() + { + return [ + // 其他Behavior + + 'statusBehavior' => [ + 'class' => StatusBehavior::class, + 'statusAttributes' => self::STATUS_ATTRIBUTES, + ], + ]; + } + + /** + * {@inheritdoc} + * 重写find()返回自定义查询类 + */ + public static function find() + { + $config = ['statusAttributes' => self::STATUS_ATTRIBUTES]; + return new MyModelQuery(get_called_class(), $config); + } +} +``` + +##### 添加文件 `MyModelQuery` + +```php + [ + * 状态位 => 状态名 + * ] + * ... + * ] + * @var array[] $statusAttributes 融合状态表 + */ + public $statusAttributes; + + /** + * @param string[] $queryParams + * @return GoodQuery + */ + public function andWhereStatus($queryParams = []) + { + return $this->andWhere($this->getStatusCondition($queryParams)); + } + + /** + * @param string[] $queryParams + * @return GoodQuery + */ + public function orWhereStatus($queryParams = []) + { + return $this->orWhere($this->getStatusCondition($queryParams)); + } + + /** + * @param array $queryParams + * @return Expression + */ + public function getStatusCondition($queryParams = []) + { + $queryAttributes = array_keys($queryParams); + foreach ($this->statusAttributes as $field => $attributes) { + $mask = $res = 0; + foreach ($attributes as $pos => $attribute) { + if (in_array($attribute, $queryAttributes)) { + $mask += 1 << $pos; + $res += $queryParams[$attribute] << $pos; + } + } + if ($mask != 0) { + $conditions[] = "$field & $mask = $res"; + } + } + return new Expression(implode('and', $conditions)); + } +} +``` + +### Usage + +##### Search + +```php +$myModels = MyModel::find() + ->andWhereStatus(['s0' => 1, 's1' => 0]) + ->orWhereStatus(['s2' => 0, 's3' => 1]) + ->all(); +``` \ No newline at end of file