你们是否遇到过一张表中有很多个标识是否的字段
我们现在打个比方,我们有四种饮料,分别是 可乐,雪碧,咖啡,茶.. 我们有个人,我们想知道这个人是否有这几种饮料的其中一种或者多种,我们通常会设计如下表(以下均是0否1是)
id | has_cola | has_sprite | has_coffee | has_tea |
---|---|---|---|---|
用户id | 是否有可乐 | 是否有雪碧 | 是否有咖啡 | 是否有茶 |
这样一来极大的浪费了数据库的字段,字段一多..还容易懵逼...而且这些字段.还经常被用到..且加索引基本没什么用的...
那么我们是否可以用一个字段来记录多种状态呢... 答案是可以得..请大家去看下参考文章.我这里只提供encode和decode代码
$statusArray = [
1 => 1,//可乐
2 => 2,//雪碧
4 => 4,//咖啡
8 => 8//茶
];
这一步其实就是列出,一个状态是否包含某一种,或者某几种状态值
//你要包含的状态
$nums = [1];
$statusArray = [
1 => 1,//可乐
2 => 2,//雪碧
4 => 4,//咖啡
8 => 8//茶
];
$header = [];
$footer = [];
foreach ($statusArray as $item) {
if (in_array($item, $nums)) {
$header[] = $item;
} else {
$footer[] = $item;
}
}
$combination = [array_sum($nums)];
$step = 0;
while (count($footer) > 1) {
if ($step > 0) {
$head = array_shift($footer);
$header[] = $head;
}
$count = count($footer);
for ($i = 0; $i < $count; $i++) {
$combination[] = array_sum($header) + $footer[ $i ];
}
++$step;
}
var_dump($combination);
这个其实就是根据一个最终值,反解出你又多少个状态
/**
* 根据一个状态值反解出有的状态值
*
* @param array $statusArray
* @param int $number
* @param int $base
*
* @return array
*/
function decodeStatus (array $statusArray, int $number, int $base = 2)
{
if ($number < 0) throw new \Exception('被解必须大于0');
if (!$statusArray) throw new \Exception('基本数据为空');
if ($base <= 0) throw new \Exception('基数必须大于0');
$maxCount = count($statusArray) - 1;
$list = [];
for ($i = $maxCount; $i >= 0; $i--) {
$index = pow($base, $i);
$temp = $number - $index;
if ($temp >= 0) {
$list[] = $index;
$number = $temp;
}
}
return $list;
}