我必须在数据库中存储一些true / false值,而不是创建很多列,而是使用单个int
列,我存储所有布尔值,使用Bitwise运算符压缩
示例:
Product 1
被认证为:
Lead Free - Yes
Gluton Free - No
Free Range - Yes
Organic - Yes
因此,在数据库的certs
列中,我将1
,0
,1
,1
压缩为13
(1 + 4 + 8)。
我编写了快速包装函数来压缩和提取这些信息(从int
更改为boolean
数组并返回)。
我不确定快速添加和删除此值的最佳方法。假设我想将产品更新为不再是免费范围。我可以使用压缩的int,减去4
。这样可行。除非它已经不是自由范围了怎么办?如果我正在进行批量操作,我需要我的功能只从当前认证的自由范围的产品中删除4
,否则数字会搞乱。
我已经用冗长的if
语句弄明白了,但它并不优雅。这有效:
// $certs_current is the compressed int from the DB.
// $certs_new is a new integer. 4 would mean toggle "Free Range" to true. -4 would mean toggle it to false.
if ( $certs_current & abs($certs_new) ) {
if ( $certs_new < 0 ) {
$certs_current += $certs_new;
}
} else {
if ( $certs_new > 0 ) {
$certs_current += $certs_new;
}
}
这是很多if
陈述。我使用|
运算符,但它只适用于添加正数。将它传递给-4
然后就会中断。我无法找出nor
运营商。
有更好的方法吗?
修改
换句话说,是否有运营商:如果我给它13
和-4
,它会给我9
。但如果我给它9
和-4
,它会给9
?或者甚至只是13
和4
。
修改2
将|
添加到我的工作逻辑中,我已经降低了复杂性并且仍然有效:
if ( $certs_new > 0 ) {
$certs_current = ( $certs_current | $certs_new );
} else {
if ( $certs_current & abs($certs_new) ) {
$certs_current += $certs_new;
}
}
基本上它说,如果新数字是正数,那么如果需要添加,请使用|
运算符添加它。如果它是否定的,那么我们首先检查是否需要删除它,如果是,则删除它。哪个是我认为我们可以改进的地方。
|
替换if
语句,因为如果4
尚未切换为true,它只会添加4
(我意识到这是一种奇怪的方式描述它。)
但是对于负数,我仍然有一个嵌套的if
语句,如果可能的话,这就是我要删除的内容。
答案 0 :(得分:0)
您拥有压缩值,那么为什么不在进行操作之前将其展开?
$certs_temp = $certs_current
$is_organic = $certs_temp >= 8 && $certs_temp -= 8
$is_freerange = $certs_temp >= 4 && $certs_temp -= 4
$is_glutenfree = $certs_temp >= 2 && $certs_temp -= 2
$is_leadfree = $certs_temp >= 1 && $certs_temp -= 1
然后使用更改的值重新压缩(如果确实发生了任何变化)。
如果您尝试直接对存储的整数进行操作,我认为您会遇到麻烦,该整数实际上代表4个单独的二进制标志。要么在DB中单独表示每个标志,要么必须将其存储为整数,然后在应用更改或逻辑之前对其进行解码。
答案 1 :(得分:0)
我明白了。要将布尔值切换为false,我们需要:
使用~
(示例中为13
)从数据库中反转主压缩int
使用4
添加新int -4
(不是|
)的绝对值。
使用~
再次反转完整的int。
所以最终的代码只有一个if
语句:
if ( $certs_new > 0 ) {
$certs = ( $certs | $certs_new );
} else {
$certs = ~( ~$certs | abs($certs_new) );
}
// 13 and 4 .... 13
// 13 and 2 .... 15
// 13 and -4 .... 9
// 13 and -2 .... 13