这篇文章给大家介绍位运算在PHP 实际项目当中的运用是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
来回顾一下这些基础知识,同时也会讲位运算在 PHP
实际项目当中的高级技巧。
PHP 手册当中,专门对位运算及位运算符进行了使用介绍。
https://www.php.net/manual/zh/language.operators.bitwise.php
之所以称为位运算,指的是在运算过程中,我们会把两组需要位运算的数值进行二进制化,然后两组二进制的数字从低位向左对齐。这里的位指的是二进制数字的位置。而按位与运算符指的是两组数值每一位相与,同为 1 则 结果为 1,否则为 0。
看 PHP 示例:
echo 1 & 3; // 输出:1
为什么会输出 1 呢?
那是因为:
1 的二进制表示结果为:01。
3 的二进制表示结果为:11。
那么这两组二进制结果对齐之后的运算流程如下:
0111——01
从右往左进行位运算,都 为 1 则结果为1,否则为 0。结果自然是 01。而 01 转换成十进制就是 1 。所以,输出的结果为 1。
再看一组示例吧:
echo 2 & 10; // 输出:2
我们来看看运算过程:
101010——————0010
0010 转换成十进制就是 2。
一定要记得是向左对齐。或者称为低位顺位对齐模式。
如果你不会十进制转二进制或二进制转十进制不会。那么,下面这两个方法能帮助你。
echo decbin(10); // 十进制转二进制。echo bindec(10); // 二进制转十进制。
这个跟上面的按位与运算符稍微有一点不同:只要两组数字当中有只要有一位是 1 则结果就为 1。
看示例:
echo 2 | 10; // 输出结果:10
运算过程:
101010——————1010
1010 的十进制结果就是 10。
这个运算符比较有意思:两组数字必须是一组 0 与 1 结果才为 1。1 与 1 和 0 与1 都是 0。
看示例:
echo 1 ^ 1; // 输出结果:0echo 1 ^ 0; // 输出结果:1
1 ^ 1 运算过程:
01 01 —— 00
1 ^ 0 运算过程:
0100——01
这个很简单。没啥好说的。反正不相同就为 1,相同就为 0。
~ 按位取反运算符、>> 右移运算符、<< 左移运算符。它们的操作数都是一个。所以,与上面的两个操作数的位运算符有着非常明显的区别。在 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 个条件才能访问就不行了。或者,一个满足另外一个取反。
优点明显,同样缺点也很明显。大家要根据实际情况来选用。
关于位运算在PHP 实际项目当中的运用是怎样的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。