PHP8中字符串与数字的比较更智能

2022-10-11 21:17:21 195 0
魁首哥

PHP8.0 发布[1]也有一段时间了,此次发布带来了很多实用且强大的功能,比如:

  1. Named arguments
 // php 7.x
htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);

// php 8.0
htmlspecialchars($string, double_encode: false);  

传递参数时,可以通过指定参数名传递。

PHP8中字符串与数字的比较更智能

  1. Constructor property promotion
 // php 7.x
class Point {
  public float $x;
  public float $y;
  public float $z;

  public function __construct(
    float $x = 0.0,
    float $y = 0.0,
    float $z = 0.0
  ) {
    $this->x = $x;
    $this->y = $y;
    $this->z = $z;
  }
}

// php 8.0
class Point {
  public function __construct(
    public float $x = 0.0,
    public float $y = 0.0,
    public float $z = 0.0,
  ) {}
}  

构造器参数向上提升,这个还挺有意思的,构造器中的参数(公众号 正义 的程序 猿)直接变成了类的属性,大大简化了代码量。

  1. Union types
 // php 7.x
class Number {
  /** @var int|float */
  private $number;

  /**
   * @param float|int $number
   */
  public function __construct($number) {
    $this->number = $number;
    // 公众号 正义的程序猿
  }
}

new Number('NaN'); // Ok

// php 8.0
class Number {
  public function __construct(
    private int|float $number
  ) {}
}

new Number('NaN'); // TypeError
  

在之前的版本,申明联合变量类型都是通(公众号 正义的程序猿)过注解的方式,而在8.0中,结合构造函数变量提升,直接在定义的时候申明联合类型,并且在8.0中是严格的,类型不匹配直接在运行时报错。

当然,8.0中的feature不止这些,还有很多。这里来详细说一下 Saner string to number comparisons ,就是本文的标题。

现象

PHP中在比较时,我们经常这样操作:

 10 == '10'  

结果符合我们的预期,但这样并不是每次都正确,比如:

 // php 7.x
0 == 'foobar' // true
  
// php 8.0
0 == 'foobar' // false  

是不是很诡异?

再来一个:

 // php 7.x
var_dump(in_array(0, ['foo', 'bar'])); // true

// php 8.0
var_dump(in_array(0, ['foo', 'bar'])); // false  

还有:

 // php 7.x
$v = 0;

switch ($v) {
    case 'bar':
        echo 'baaar' . PHP_EOL;
    case 0:
        echo 'foo' . PHP_EOL;
}

// 输出:
// baaar
// foo

// PHP 8.0
// 输出
// foo  

为什么

先来说一下PHP中的比较运算,分为两类,严格类型( === , !== )和非严格类型( == , != , > , >= , 两者的主要区别如下:

  • 严格类型比较底层用的是 strcmp() ,非严格类型使用的是所谓的“智能”比较,即将字符串转为数字对比
  • 在比较数组时,严格类型不光会比较 ,还会比较 索引 的顺序,非严格类型只会简单的比较值
  • 在比较对象时,严格类型使用对象标识符比较,非严格类型只会比较对象的值

在使用 == 比较 数字 字符串 时,PHP 8.0之前的版本会先将 字符串 转换为 数字 ,之后再做两个数字间的比较,这也就是为什么上门 0 == “foobar” = true 了。

Saner string to number comparisons

文章标题说PHP8中字符串与数字的比较更智能,具体智能在哪里?针对上面的问题,8.0当中引入 Saner string to number comparisons 这个特性[2],底层具体的操作为:当比较 数字字符 时,使用数字与数字对比,而 其他字符与数字 比较时,统一使用字符串比较。我们来通过一个表格来对比下前后的变化:

 Comparison    | Before | After
------------------------------
 0 == "0"     | true   | true
 0 == "0.0"   | true   | true
 0 == "foo"   | true   | false
 0 == ""      | true   | false
42 == "   42" | true   | true
42 == "42foo" | true   | false
  

参考:

收藏
分享
海报
0 条评论
195
上一篇:php编码规范有哪些? 下一篇:PHP程序员常跳的坑,来看看你跳过吗?

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码