Press "Enter" to skip to content

PHP8新特性之match表达式

PHP8 alpha2发布了,最近引入了一个新的关键字:match, 这个关键字的作用跟switch有点类似。

虽然我一般对语法糖无感,但这个我觉得还是有点意思,match这个词也挺好看,那么它是干啥的呢?

在以前我们可能会经常使用switch做值转换类的工作,类似:

switch ($input) {
    case "true":
        $result = 1;
    break;
    case "false":
        $result = 0;
    break;
    case "null":
        $result = NULL;
    break;
}

(当然,有的同学会说,谁会这么写,用个数组转换不行么? 拜托,这是举例啊,数组也只能数字键和整数啊,万一key是需要其他表达式呢,万一你要多个key对应一个值呢,对吧?)

那么如果使用match关键字呢,可以变成类似:

$result = match($input) {
        "true" => 1,
        "false" => 0,
        "null" => NULL,
};

相比switch, match会直接返回值,可以直接赋值给$result了。

并且,类似switch的多个case一个block一样,match的多个条件也可以写在一起,比如:

$result = match($input) {
    "true", "on" => 1,
    "false", "off" => 0,
    "null", "empty", "NaN" => NULL,
};

需要注意的和switch不太一样的是,以前我们用switch可能会经常遇到这种诡异的问题:

$input = "2 person";
switch ($input) {
    case 2:
        echo "bad";
    break;
}

你会发现,bad竟然被输出了,这是因为switch使用了宽松比较(==)。match就不会有这个问题了, 它使用的是严格比较(===),就是值和类型都要完全相等。

还有就是,当input并不能被match中的所有条件满足的时候,match会抛出一个UnhandledMatchError exception:

$input = "false";
$result = match($input) {
        "true" => 1,
};

会得到:

Fatal error: Uncaught UnhandledMatchError: Unhandled match value of type string

这样就不用担心万一match条件没写全导致了不可预知的错误。

另外还是要说明,match是关键字,也就是从PHP8开始它不能出现在namespace或者类名中,如果你的项目中有用match作为类名的:

class Match {}

在PHP8开始将会得到语法错误了, 当然,方法名中还是可以用的。

详细的,可以参考RFC:Match Expression

以上,没了。

24 Comments

  1. jee
    jee September 29, 2020

    这个跟自己封装一个有啥区别

  2. jee
    jee September 29, 2020

    没啥作用

  3. chenpingbin
    chenpingbin September 17, 2020

    match 方法 虽然能抛出异常,但实际场景中很多的时候会有default 这个可能是match方法的一个短板。

  4. Ganlv
    Ganlv September 9, 2020

    php 的优势在于,发布容易、运维简单、语法简单、开发快速

    基于 HTTP 协议、请求回应式、REST API 这类东西都可以使用,而且天然的可以水平扩展。

    php 通常作为后端中的前端,由于业务侧可能经常变动,对外的接口可能会各种改变,php 的动态性非常棒,go 在这些方面是没法比的。

    真后端就是数据库、其他各种算法服务器了,这些服务是有状态的,php 不适合,这是 go 的主战场。

    • shan
      shan September 16, 2020

      转向RUST开发者表示GO就算了吧 哈哈
      match 在rust叫模式匹配.并不是简单的=== 配合enum牛逼的一逼.

    • 啦啦啦
      啦啦啦 September 2, 2020

      啦啦啦啦啦我来啦啦啦啦啦啦我来啦

  5. oforz
    oforz August 21, 2020

    鸟哥,都PHP8了,还不考虑支持一下字符串的切片操作吗,就是python那样的 $abc[123:456]。现在使用函数调用substr,如果改为切片语法,应该对大量的临时分割效率有很大提高吧,像以前的unpack,现在是提供了第三个$offset参数,如果直接切片能通用得多了。

  6. owa10086
    owa10086 August 19, 2020

    js的switch是全等比较,和php有时候老是搞混

  7. Mark
    Mark August 15, 2020

    hi,冒昧打扰,
    其实有个困扰在我心中许久了,望能抽空解答下。

    PHP对于金额的计算,一般采取bc系列函數進行,
    而使用mysql存储时候,数据类型会通过decimal来存储。

    但是如果想在PHP中写个函数计算金额,之前得写法是:

    function addMoney($money,$numCnt=1){
    return bcmul($money,$numCnt,2);
    }

    如果希望指定数据类型,请问该怎么处理?
    如:
    function addMoney(float $money,int $numCnt):string
    {
    return bcmul($money,$numCnt,2);
    }

    这样感觉有点奇怪,MYSQL的decimal类型我不清楚是通过什么形式实现的,
    但是PHP有相对应的类型吗?float/double吗?如果数量过大会否有BUG?

    • Violet_ice紫冰
      Violet_ice紫冰 September 11, 2020

      是string类型

  8. Emrys.Liu
    Emrys.Liu July 23, 2020

    match 语法 alpha2 测试报解析错误, alpha3 才成功

  9. oforz
    oforz July 23, 2020

    鸟哥,PHP的array已经实现用[]赋值,有没有考虑过用{}来实现对象的定义?比较喜欢用对象的方式来做配置和参数,但是PHP的对象属性不能一次性初始化,很不方便。

    • Ganlv
      Ganlv September 9, 2020

      如果怕语法出错,像 JavaScript 解决箭头函数的函数体和直接返回值一样,加括号也行啊 ({a: 1})

  10. bao
    bao July 16, 2020

    说出理由

  11. a
    a July 14, 2020

    借鉴rust?

    • 白菜
      白菜 July 15, 2020

      这模式我第一看的时候是在erlang。不能说借鉴rust,rust也是集大成者。

  12. 雷柏利
    雷柏利 July 14, 2020

    您好!鸟哥。我是一名在国内4线城市的普通php开发者。php社区可不可以成立php基金会?借助php基金会推广、保护并提升php编程语言,促进php社区持续发展。php在我们国内使用还是相对比较多,以我们国家的国力水平维护一个全球性的编程语言基金会应该不会太差。

    • hello
      hello July 14, 2020

      转go吧

      • 恩佐Enzo
        恩佐Enzo August 20, 2020

        从楼主表达中 可见对php 热爱之情!你这句话 有点扎心啊 兄嘚!

      • shan
        shan September 16, 2020

        RUST表示学GO不如洗洗睡吧.
        不搞语言混战
        GO的优势比PHP块 但对RUST来说呵呵
        PHP比GO慢 但你一个PHPER转GO意义在哪?

    • Ben Huang
      Ben Huang July 17, 2020

      组织整合社区感觉可行,成立基金会大公司牵头更好些,社区牵头没核心经济来源额

Leave a Reply

Your email address will not be published. Required fields are marked *