发布于2021-03-14 05:54 阅读(1039) 评论(0) 点赞(11) 收藏(5)
我们首先来看一个系统中常见的需求:
有一个广告表,我们要对广告做显示控制:
可能的表结构如下:
CREATE TABLE `finger_ad` (
`ad_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`ad_name` varchar(50) NOT NULL COMMENT '广告名称',
`ad_image_url` varchar(255) NOT NULL COMMENT '广告图片',
`ad_url` varchar(255) NOT NULL COMMENT '广告图片URL跳转地址',
`is_vip` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否仅限 VIP 显示',
`display` tinyint(1) NOT NULL DEFAULT '1' COMMENT '显示状态:1显示、0隐藏',
PRIMARY KEY (`ad_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='广告表';
假如后期,我们需求更改了。需要再增加几种限制:
遇到这种限制条件的需求,开发同学是不是很伤脑筋?
可能很多开发第一反应就是在表结构增加这种新增的限制条件字段。一切看来似乎很美好。
的确,这样添加字段是最快最容易的方式。也能完成我们的需求。
但是,这样会引来如下毛病:
那么,还有没有更好的方式解决这些问题呢?
答案:有!
这就是我们今天要讲的按位与运算符的高级技巧。
我们把上面的表结构改一下:
DROP TABLE IF EXISTS `finger_ad`;
CREATE TABLE `finger_ad` (
`ad_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`ad_name` varchar(50) NOT NULL COMMENT '广告名称',
`ad_image_url` varchar(255) NOT NULL COMMENT '广告图片',
`ad_url` varchar(255) NOT NULL COMMENT '广告图片URL跳转地址',
`bit_condition` INT(11) UNSIGNED NOT NULL COMMENT '位运算条件:1-登录可访问、2-未登录可访问、4-30天注册可访问、8-30天未登录可访问、16-未消费可访问、32-VIP可访问',
`display` tinyint(1) NOT NULL DEFAULT '1' COMMENT '显示状态:1显示、0隐藏',
PRIMARY KEY (`ad_id`)
) ENGINE=InnoDB DEFAULT CHARSET UTF8 COMMENT='广告表';
我们把所有的条件都去掉了。增加了一个字段: bit_condition
。把所有的条件都组合到一个字段。
那我们此时该如何写代码呢?
比如,现在要添加如下限制条件的广告:
只允许登录用户访问或已注册 30 天用户或是 VIP 用户才允许访问该广告。
那么,这个广告的 bit_condition
该如何设置值呢?很简单,把这几个条件的位值直接相加。此时值为:37。
很多可能会很奇怪。设置为 37 ,我怎么知道是这几个值的和呢?如果对 Linux 系统权限熟悉的同学就很容易理解这种做法。实际上,这里运用了按位与运算的特性:任意组合相加的值不会重复。
这个理解起来有一定难度。我三两句也很难给你梳理明白。大家可以在网上深入挖掘一下这方面儿的知识。你只需要知道这一点特点即可。
那么,现在我们该如何写 SQL 呢?
示例如下:
SELECT * FROM finger_ad WHERE display = 1 AND bit_condition & 3 = bit_condition
这条 SQL 语句当中的 3 对应的是当前用户针对这么多条件得到的数值。如果 bit_condition
位值是与 3 按位与与 bit_condition
结果相同,说明条件符合。
我们通过一个字段解决了所有条件的问题。着实得感谢按位与运算符的特性。同时也对 MySQL
能支持位运算符感到开心。
那么,它有什么缺点呢?
想必有经验的同学已经看出来了。这种写法只能满足包含关系。假如要实现同时满足 3 个条件才能访问就不行了。或者,一个满足另外一个取反。
优点明显,同样缺点也很明显。大家要根据实际情况来选用。
扩展学习文件:
<?php
//例子1
echo '<h2>demo1</h2><br>';
//定义常量
define('D1',1);
define('D2',2);
define('D3',4);
define('D4',8);
define('D5',16);
function showStatus($state){
for($i= 1;$i<=5;$i++){
$d = 'D'.$i;
$dd = constant($d); //取对应常量的值
if(($state & $dd) > 0){
echo '第'.$i.'盏灯亮'.'<br>'; //8
}else{
echo '<span style="color: red">第'.$i.'盏灯灭</span>'.'<br>';
}
}
echo "sql语句写法:SELECT * FROM `table` WHERE state & {$state} = state;";
echo '<br>';
echo '<br>';
}
$state = D4;
showStatus($state); //只开第4盏灯
$state = D1;
showStatus($state); //只开第1盏灯
$state = D4 | D1;
showStatus($state); //开第1盏灯和第4盏灯
$state = (D4 | D2 | D1) & (~D1);
showStatus($state); //开第1盏灯,第2盏灯和第4盏灯,然后关闭第1盏灯
//例子2
echo '<h2>demo2</h2><br>';
/**
* 1、权限应用
* 拥有哪些权限,就把这些权限对应的数值加起来
* 例如:版主拥有权限(增加、删除、修改、查询),则版主的权限值存储为15(8+4+2+1)
* 然后【权限值之和】 与 【实际权限值】做【位于】比较
* 结果是真则拥有权限
* 结果是假则没有权限
*
* 注意:权限值必须是2的N次方,从0次方开始,31次方是2147483648
* 32次方是4294967296,已超过了常用int(10)最大存储4294967295,所以必须注意权限数量(<31个)
* 当然如果存储格式为bitint或varchar等可以存储更长数字的格式,那么权限数量可以继续增加
*/
// 赋予权限值-->删除:8、上传:4、写入:2、只读:1
define('mDELETE',8);
define('mUPLOAD',4);
define('mWRITE',2);
define('mREAD',1);
//vvvvvvvvvvvvv使用说明vvvvvvvvvvvvv
//部门经理的权限为(假设它拥有此部门的所有权限),| 是位或运行符,不熟悉的就查查资料
echo '全部权限为:'.(mDELETE|mUPLOAD|mWRITE|mREAD).'<br>';// 相当于是把上面的权限值加起来:8+4+2+1=15
/*
*赋予它多个权限就分别取得权限值相加,又比如某位员工拥有除了删除外的权限其余都拥有,那它的权限值是多少?
*应该是:4+2+1=7
*/
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//判断某人的权限可用,设权限值在$key中
/*
*判断权限用&位与符,
*/
// 设我只有 upload 和 read 权限,则
$key = (mUPLOAD|mREAD);//相当于是把上传、只读的权限值分别相加:4+1=5
echo '当前权限为:'.$key.'<br>';;
if($key & mDELETE){
echo '有删除权限'.'<br>'; //8
}else{
echo '<span style="color: red">无删除权限</span>'.'<br>'; //8
}
if($key & mUPLOAD){
echo '有上传权限'.'<br>'; //4
} else{
echo '<span style="color: red">无上传权限</span>'.'<br>'; //4
}
if($key & mWRITE){
echo '有写入权限'.'<br>'; //2
} else{
echo '<span style="color: red">无写入权限</span>'.'<br>'; //2
}
if($key & mREAD){
echo '有只读权限'.'<br>'; //1
} else{
echo '<span style="color: red">无只读权限</span>'.'<br>'; //1
}
?>
运行结果:
对PHP后端技术,对PHP架构技术感兴趣的朋友,我的官方群1023755567点击此处,一起学习,相互讨论。
群内已经有管理将知识体系整理好(源码,学习视频等资料),欢迎加群免费领取。
原文链接:https://www.cnblogs.com/miss-cc/p/13614988.html
作者:肚子里的大哥
链接:http://www.phpheidong.com/blog/article/3162/98b601355f63103fc4ad/
来源:php黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 php黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-4
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!