您当前的位置:首页 > 网站建设笔记 >

&运算符的巧妙应用

0

&:按位与。以$a & $b为例,将$a和$b转化为二进制后,都为1的位设为1。

$a=6;
$b=3;
var_dump($a & $b);
输出int(2)

原理:

  • $a=6 将数字6转化为二进制为110
  • $b=3 将数字3转化为二进制为11
  • $a & $b 即是110与11
  • 将$a和$b中都为1的位设为1,位数不够的补0,即110与011
  • 运算结果010,转化为十进制结果为2

应用:

需求:这是一个设置消息提醒的功能。我们假设这是一个blog系统,用户希望有人收藏自己的文章后,可以得到一个消息提醒。这里有三种提醒方式:邮箱提醒、短信提醒、微信公众号提醒,用户可以通过开关按钮控制某种提醒方式是开启还是关闭。可以参考以下表格:

提醒操作邮箱短信微信公众号
文章被收藏开关按钮开关按钮开关按钮
被关注开关按钮开关按钮开关按钮
有人评论开关按钮开关按钮开关按钮

实现:

1、数据库设计,表名remind。

字段数据类型默认值
collection(文章被收藏)intdefault(0)
followed(被关注)intdefault(0)
commented(有人评论)intdefault(0)

2、在Remind Model中设置执行操作的提醒方式类型:

cosnt REMIND_NO=0;//关闭所有的提醒
cosnt REMIND_EMAIL=1;//邮箱提醒, 2的0次方(任何数的0次方都等于1), 1转换为二进制是1。
cosnt REMIND_SMS=2;//短信提醒, 2的1次方, 2转换为二进制是10。
cosnt REMIND_WECHAT=4;//微信公众号提醒, 2的2次方, 4转换为二进制是100。

如果有新的提醒方式值应为8、16、32以此类推(2的n次方)。

仔细观察二进制转化后:

  • email第一位是1,sms第二位是1,wechat第三位是1。
  • 即email占领了第一位、sms占领了第二位、wechat占领了第三位。
  • 1代表开启提醒,0代表关闭提醒。
  • 如果第一位是1,表示开启邮箱提醒,如果第一位是0,表示关闭邮箱提醒。

假设用户希望有人评论他的文章时,收到来自系统的提醒:

  • 只开启邮箱提醒,那数据库中commented字段对应的值是1,1转换为二进制等于1
  • 只开启短信提醒,那数据库中commented字段对应的值是2,2转换为二进制等于10
  • 只开启微信公众号提醒,那数据库中commented字段对应的值是4,4转换为二进制等于100
  • 如果开启邮箱提醒和短信提醒,那数据库中commented字段对应的值是1+2=3,3转换为二进制等于11
  • 如果开启邮箱提醒和微信公众号提醒,那数据库中commented字段对应的值是1+4=5,5转换为二进制等于101
  • 如果开启短信提醒和微信公众号提醒,那数据库中commented字段对应的值是2+4=6,6转换为二进制等于110
  • 如果开启所有提醒,那数据库中commented字段对应的值是1+2+4=7,7转换为二进制等于111

3、控制器中写具体业务逻辑:

用户希望有人关注他后,可以通过邮箱提醒他,所以用户开启了邮箱提醒:

  • 前端传值:['option'=>'followed','type'=>'email']
  • 后端接收到参数,从数据库中找到当前用户的这一条数据,得知followed字段值为0
  • email对应的值为1,进行&运算,判断email提醒是否开启
  • 1&0=0,所以未开启,那我们要开启email提醒,此时followed=0+1=1

后来用户觉得短信提醒比较直接,所以又开启了短信提醒:

  • 前端传值:['option'=>'followed','type'=>'sms']
  • 后端接收到参数,从数据库中找到当前用户的这一条数据,得知followed字段值为1
  • sms对应的值为2,进行&运算,判断sms提醒是否开启
  • 2&1=0,所以未开启,那我们要开启sms提醒,此时followed=2+1=3

后来该用户越来越厉害,每天关注他的人特别多,每天都收到很多消息,所以他想关闭短信提醒:

  • 前端传值:['option'=>'followed','type'=>'sms']
  • 后端接收到参数,从数据库中找到当前用户的这一条数据,得知followed字段值为3
  • sms对应的值为2,进行&运算,判断sms提醒是否开启
  • 2&3=2,所以已开启,那我们要关闭sms提醒,此时followed=3-2=1
$option=$_GET['option'];//提醒操作,由前端传来的值
$type=$_GET['type'];//提醒方式,由前端传来的值

$remind=Remind::model()->find(1);//根据条件,在数据库中找到的一条记录

if($type=='sms'){
  if($remind->$option & Remind::REMIND_SMS)
  {
    //true代表已开启sms提醒,此时应关闭sms提醒
    $remind->$option -= Remind::REMIND_SMS;
  }
  elseif(!($remind->$option & Remind::REMIND_SMS))
  {
    //false代表已关闭sms提醒,此时应开启sms提醒
    $remind->$option += Remind::REMIND_SMS;
  }
}
顶部中部底部