思考:通过逻辑运算符来优化PHP代码

发布于 2023-05-30  530 次阅读


内容纲要

PHP的逻辑运算符有四个:

  • and 逻辑与
  • or 逻辑或
  • && 逻辑与
  • || 逻辑或
  • xor 逻辑异或
  • ! 逻辑非

针对逻辑与和逻辑或运算符可以对某些特定的代码进行优化。

1.逻辑与

逻辑与指在运算符两侧的表达式同时为true时返回true,如果不同时为true则返回false,思考一下,因为and必须将两个值进行比较,并且两个值都要是true才会返回true,那么and在执行时,对第一个值进行判断,如果时true,则继续判断第二个值,如果时false,则此时表达式必然不成立,这条语句就是被截断并且返回false。

基于此可以利用逻辑与运算符代替if进行判断,当前and前的表达式为true才执行and后的表达式,相当于:

if(exp1==true){
//code here;
}

简单的测试一下:

$a=10;
$b=100;
if($a==10){
$b=50;
}
echo $b;

显然输出是50,那么将这条if语句通过and尝试一句话完成:

$a=10;
$b=100;
$a==10 and $b=50;
echo $b;

结果仍然是50,如果第一个表达式是false,后面的表达式还会不会执行?

$a=10;
$b=100;
$a>10 and $b=50;
echo $b;

结果是100,由此发现如果and前的表达式是false,则后面的表达式也不会被执行。

总结:对于类似判断某一值为真才能执行的if语句,可以通过and来缩短代码量。

if(exp == true){
//action
}

可以替换为:

exp and action

进一步的,如果对多个条件进行判断:

if($user['name']=='admin' and $user['passwd']==123456){
echo "登录成功";
login();
}

使用and:

[$user['name'],$user['passwd']==['admin',123456] and login();

但是这种方法只能用于后面的表达式被完全封装为一个函数或者方法,否则会产生错误。

并且,不适用于赋值语句,当尝试用and对语句赋值时,因为and本质是用于对两个表达式进行比较,所以他只会返回布尔值,例如:

$a=20;
$b=100;
$c= $a<$b and $b;

这只能通过三目运算符实现:

$c= $a<$b ? $b :$a;

或者也可以这样:

$a<$b and $c=$b;

简单的应用:

通过and简化一个流程控制语句,情景是用户购买商品,封装了购买商品的方法buy(),在用户余额大于商品,且当前商品库存不为0时调用buy进行下单操作。

$user=new User();
$balance=$user->balance;
$goods=new Goods();
$left=$goods->left;
$price=$goods->price;
function buy(){
echo "购买成功";
}
if($balance>=$price and $left>0){
buy();
}

使用and:

($balance >= $price and $left>0) and buy();

最后总结:

and 如果用在流程控制中,实际上就是判断第一个表达式的值是否为true,如果为true则执行后面的语句,否则返回false,可以通过小括号进行多重嵌套。

&&与and作用一样,二者都是表示逻辑与运算,经过测试,以上代码将and换为&&都可以正常执行。

2.逻辑或

逻辑或在逻辑运算中表示二者有一个及以上为true即得到true,如果都是false则返回false。

在语句执行上,逻辑或首先判断第一个表达式是否为true,如果为true,则无论第二个是否为true都返回true,因此第二条语句将不会被执行。

典型的例子:赋值语句在被赋值的变量内容不为空或者false时始终为true,通过两个变量以or来比较赋值:

$d=10 or $f=1;
var_dump($d,$f);
$d="" or $f=10;
var_dump($d,$f);
$d=[] or $f=20;
var_dump($d,$f);
$d=30 or $f=false;
var_dump($b,$f);

结果是:

int(10) NULL string(0) "" int(10) array(0) { } int(20) int(10) int(20)

得出当$d被赋值为false 或者空值时$f才会被复制,如果$d所在的表达式为true,则$f不会被赋值。

所以可以通过or实现简短的流程控制:

if(!empty($data)){
    insert($data);
)

可以改写为:

empty($data) or insert($data);

多层嵌套测试:

$user="admin";
$balance="50";
$passwd="123456";
$price=20;
$left=5;
$root="log/buglog/".time().".txt";
if($user == 'admin' and $passwd=="123456"){
    if($balance >= $price && $left>0){
         if(empty($root)){
              file_put_contents($root,""购买成功!");
         }
    }
}

改写:

$user="admin";
$balance="50";
$passwd="123456";
$price=20;
$left=5;
$root="log/buglog/".time().".txt";
($user=='admin' and $passwd=='123456') and (($balance >= $price && $left>0) and (file_exists($root) or file_put_conetnts($root,"购买成功")));

or运算符也可以用在程序截断上,如果在对某处代码不成立时需要截断程序:

!empty(json_decode($data)) or die("数据为空!");

而||与or的作用相同,都代表逻辑或,所以在执行语句的顺序也是一致的

3.逻辑异或

逻辑异或指两个语句有一个为true且不全为true,如果是多个语句,则从左到右进行判断是否为全部为true,只要不全为true或者全为false他都会返回true,相反则会返回false。

1 xor 0;
//true
0 xor 0;
//false
1 xor 1;
//false
1 xor 1 xor 0;
//1xor1为false,false xor 0为false
1 xor 1 xor 1;
//true
1 xor 1 xor 1 xor 1;
//false

因为xor必须确定每一个表达式的值,所以使用xor会对每一条语句都执行,不像and和or需要满足一定条件来执行后一条语句,因此xor用在流程控制上是没意义的,因为他会对每一条语句都执行。

4.!逻辑非

逻辑非用在流程控制上同样没有意义,以为他只是对一个表达式进行判断然后返回一个布尔值,他不会对是否执行产生影响(除非他用作本身的作用,进行判断)。

总结:
对于and和&&在流程控制中的作用是,当前一个表达式为true时,执行and后的语句。

对于or和||在流程控制中的作用,当前一个表达式为false时,执行后面的语句。

届ける言葉を今は育ててる
最后更新于 2023-05-30