php实际运用,位运算在 PHP 实际项目当中的高级运用

我们首先来看一个系统中常见的需求:

有一个广告表,我们要对广告做显示控制:

手动上下线。

只允许 VIP 查看。

可能的表结构如下:

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=‘广告表‘;

假如后期,我们需求更改了。需要再增加几种限制:

已登录用户

未登录用户

30 天内未登录用户

注册 30 天的用户

遇到这种限制条件的需求,开发同学是不是很伤脑筋?

可能很多开发第一反应就是在表结构增加这种新增的限制条件字段。一切看来似乎很美好。

的确,这样添加字段是最快最容易的方式。也能完成我们的需求。

但是,这样会引来如下毛病:

每次增加限制条件。我们都要增加字段。这种对数据库的更动能少改就少改。毕竟,无限制的增加字段不可取。

假如广告表数据量很大。大到增加一个字段需要几分钟的时候,这会给数据库服务器造成读写压力。

条件越多,SQL 条件语句就会越来越长。

那么,还有没有更好的方式解决这些问题呢?

答案:有!

这就是我们今天要讲的按位与运算符的高级技巧。

我们把上面的表结构改一下:

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 个条件才能访问就不行了。或者,一个满足另外一个取反。

优点明显,同样缺点也很明显。大家要根据实际情况来选用。

扩展学习文件:

<?phpecho ‘

demo1
‘;//定义常量

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.‘盏灯亮‘.‘
‘; //8

}else{echo ‘第‘.$i.‘盏灯灭‘.‘
‘;

}

}echo "sql语句写法:SELECT * FROM `table` WHERE state & {$state} = state;";echo ‘
‘;echo ‘
‘;

}$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盏灯

//

echo ‘

demo2


‘;//赋予权限值-->删除:8、上传:4、写入:2、只读:1

define(‘mDELETE‘,8);define(‘mUPLOAD‘,4);define(‘mWRITE‘,2);define(‘mREAD‘,1);//vvvvvvvvvvvvv使用说明vvvvvvvvvvvvv

//部门经理的权限为(假设它拥有此部门的所有权限),| 是位或运行符,不熟悉的就查查资料

echo ‘全部权限为:‘.(mDELETE|mUPLOAD|mWRITE|mREAD).‘
‘;//相当于是把上面的权限值加起来:8+4+2+1=15

/**赋予它多个权限就分别取得权限值相加,又比如某位员工拥有除了删除外的权限其余都拥有,那它的权限值是多少?

*应该是:4+2+1=7*/

//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

//判断某人的权限可用,设权限值在$key中/**判断权限用&位与符,*/

//设我只有 upload 和 read 权限,则

$key = (mUPLOAD|mREAD);//相当于是把上传、只读的权限值分别相加:4+1=5

echo ‘当前权限为:‘.$key.‘
‘;;if($key &mDELETE){echo ‘有删除权限‘.‘
‘; //8

}else{echo ‘无删除权限‘.‘
‘; //8

}if($key &mUPLOAD){echo ‘有上传权限‘.‘
‘; //4

} else{echo ‘无上传权限‘.‘
‘; //4

}if($key &mWRITE){echo ‘有写入权限‘.‘
‘; //2

} else{echo ‘无写入权限‘.‘
‘; //2

}if($key &mREAD){echo ‘有只读权限‘.‘
‘; //1

} else{echo ‘无只读权限‘.‘
‘; //1

}?>

运行结果:

20190814154917018692.png

原文:https://www.cnblogs.com/-mrl/p/11352348.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值