用PHP实现位标记,用PHP二进制实现类似0777权限设计

有人会问这个使用场景,比如 数据库字段你存一个用户的爱好集合,你使用json [“xx”,”xx”] 还是希望用一个int 来存集合?

目前我使用两种方案。
第一种是转换为 二进制字符串,然后从右往左 按照位是否是==1 来标记集合.
第二种使用 按位与& 来实现,是否 爱好和 用户int 命中,如果两者的任意位 命中,那么 a&b 一定>0 也就是 !=false 也就是 !==0b0

先看看原理图
dec2bin2array.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<?php
$map=[0=>"唱歌a",1=>"跳舞",2=>"洗澡",7=>'睡觉a',8=>'吃饭'];

$decNum=129; // 010000001 (len=9,max_index=8) ; result=["唱歌","吃饭"]

$bin= decbin($decNum);

$mapKeys=array_keys($map);

$maxIndex=$mapKeys;
ksort($maxIndex);

$maxIndex=array_pop($maxIndex)+1;

echo '转2进制(缩写):'.$bin."</br>";

echo '转2进制(补全最大位):'.sprintf("%0".$maxIndex."s",$bin)."</br>";

function strMethod($dec,$map){
//取最大位数+1
$mapKeys=array_keys($map);
$maxIndex=$mapKeys;
ksort($maxIndex);
$str= decbin($dec);
$result=[];
//吧 0b1000 反转为 0b0001 ,因为 mapkey的第0=> 是指 从右往左的 下标
$str=strrev($str);
for($i=0;$i<=strlen($str);$i++){
if(\in_array($i,$mapKeys) && intval($str[$i])===0b1){
$result[]=$map[$i];
}
}
return $result;
}


function bitOperation($dec,$map){

$mapKeys=array_keys($map);
$maxIndex=$mapKeys;
ksort($maxIndex);
$maxIndex=array_pop($maxIndex)+0b1;


/**
*
* array_filter结果是反转k=>v; { ["唱歌"]=> int(0) ["跳舞"]=> int(1) ["洗澡"]=> int(2) ["睡觉"]=> int(7) ["吃饭"]=> int(8) }
*
* array_filter(array,function($MapItemValue){
//return true 就是不过滤,false为过滤
//假设第1伦是 $MapItemValue=0 ; //(2== 0b10)
* 唱歌 0b0+0b1=0b1=1
0b 1
0b010000001
* result : &按位与 两个数二进制部分 相同索引的都是1才能 !=false (0b0),所以这个是1 >0
* 跳舞 0b01+0b01= 0b10=2
0b 10
0b010000001
* })
*/

return array_filter(array_flip($map),function($MapItemValue)use ($dec,$maxIndex){

// echo '本次 $MapItemValue='.sprintf("%0".$maxIndex."s",decbin(1<<$MapItemValue));
// echo ';dec='.sprintf("%0".$maxIndex."s",decbin($dec));
// echo ';&结果'. (decbin(1<<$MapItemValue)&$dec).';';
//这里犯错 (1<<$MapItemValue)&$dec!==0b00000; //这里会优先 $dec!=0b0001 然后在&
// echo ((1<<$MapItemValue)&$dec)!==0b00000;
// echo "<br>";
return ((1<<$MapItemValue)&$dec)!==0b00000;
});

}

$result1=strMethod($decNum,$map);
var_dump($result1);

echo "<br>";

$result2=bitOperation($decNum,$map);
var_dump(array_keys($result2));

最终效果

1
2
3
4
转2进制(缩写):10000001
转2进制(补全最大位):010000001
array(2) { [0]=> string(7) "唱歌a" [1]=> string(7) "睡觉a" }
array(2) { [0]=> string(7) "唱歌a" [1]=> string(7) "睡觉a" }
作者

舰长胡椒

发布于

2022-08-29

更新于

2023-10-13

许可协议

评论