• 售前

  • 售后

热门帖子
入门百科

PHP中信息格式化操作详解(MessageFormatter类)

[复制链接]
贰十岁装成熟装s 显示全部楼层 发表于 2021-8-14 15:05:40 |阅读模式 打印 上一主题 下一主题
目录


  • 媒介
  • 格式化
  • 反格式化(根据规则获取参数数组)
  • 设置获取规则
  • 格式化完整示例

    • 根据参数内容进行复数显示
    • 选择条件规则

  • 总结

媒介

在国际化组件的学习过程中,我们已经打仗过了 NumberFormatter 这种数字的格式化操纵,它可以让我们将数字转换成标准格式、货币、本地语言等情势。本日我们来学习的是另一种专门用于信息格式化的类 MessageFormatter ,它主要是针对字符串的操纵。

MessageFormatter 也是遵照的 ICU 规范,底层是 C 中的 ICU 操纵,所以和 C 相关代码的使用方式没有太大的区别。


格式化

  1. // 格式化
  2. $fmt = new MessageFormatter("zh_CN", "{0,number,integer} 只猴子在 {1,number,integer} 颗树上,每只树上有 {2,number} 只猴子");
  3. echo $fmt->format([4560, 123, 4560 / 123]), PHP_EOL;
  4. // 4,560 只猴子在 123 颗树上,每只树上有 37.073 只猴子
  5. $fmt = new MessageFormatter("de", "{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum");
  6. echo $fmt->format([4560, 123, 4560 / 123]), PHP_EOL;
  7. // 4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum
  8. echo MessageFormatter::formatMessage("zh_CN", "{0,number,integer} 只猴子在 {1,number,integer} 颗树上,每只树上有 {2,number} 只猴子", [4560, 123, 4560 / 123]), PHP_EOL;
  9. // 4,560 只猴子在 123 颗树上,每只树上有 37.073 只猴子
  10. echo MessageFormatter::formatMessage("de", "{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum", [4560, 123, 4560 / 123]), PHP_EOL;
  11. // 4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum
复制代码
看到了吗?雷同于 PDO 里预编译操纵的占位符。在调用 format() 方法后,就可以让这个方法里面的参数来更换占位符的内容。我们可以指定占位的所使用的参数范例和位置,{参数下标,范例,扩展范例} 这就是这个信息数据格式化的占位符的规则定义。看起来貌似很简单呀,着实它还有更多的功能,我们将在反面看到。不外需要注意的是,它只支持数字、日期、文本片断范例,文章最后的参考链接中有官方的文档可以查阅。

MessageFormatter::formatMessage() 这个静态方法可以一次性地指定语言、预操纵语句以及更换参数,不需要先进行实例化再调用 format() 方法。


反格式化(根据规则获取参数数组)


可以或许进行格式化,固然我们也可以或许根据语句规则来反格式化相关的字符串从而得到对应占位符的参数列表。
  1. // 根据格式化规则反向获取规则参数
  2. $fmt = new MessageFormatter('zh_CN', "{0,number,integer} 只猴子在 {1,number,integer} 颗树上,每只树上有 {2,number} 只猴子");
  3. $res = $fmt->parse("4,560 只猴子在 123 树上,每只树上有 37.073 只猴子");
  4. var_export($res); // false
  5. echo "ERROR: " . $fmt->getErrorMessage() . " (" . $fmt->getErrorCode() . ")\n";
  6. // ERROR: Parsing failed: U_MESSAGE_PARSE_ERROR (6)
  7. $fmt = new MessageFormatter('en_US', "{0,number,integer} monkeys on {1,number,integer} trees make {2,number} monkeys per tree");
  8. $res = $fmt->parse("4,560 monkeys on 123 trees make 37.073 monkeys per tree");
  9. var_export($res);
  10. // array (
  11. //     0 => 4560,
  12. //     1 => 123,
  13. //     2 => 37.073,
  14. //   )
  15. $fmt = new MessageFormatter('de', "{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum");
  16. $res = $fmt->parse("4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum");
  17. var_export($res);
  18. // array (
  19. //     0 => 4560,
  20. //     1 => 123,
  21. //     2 => 37.073,
  22. //   )
  23. $fmt = MessageFormatter::parseMessage('de', "{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum", "4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum");
  24. var_export($fmt);
  25. // array (
  26. //     0 => 4560,
  27. //     1 => 123,
  28. //     2 => 37.073,
  29. //   )
复制代码
使用实例化后的 parse() 方法大概直接使用静态方法 MessageFormatter::parseMessage() 就可以或许实现如许的操纵。需要注意的是,对于 zh_CN ,也就是中文语言地域设置来说,这个操纵是会出题目的。通过 getErrorMessage() 和 getErrorCode() 就可以看到错误信息以及错误代码,可以看到对于中文来说,直接返回的错误信息就是解析失败。


设置获取规则


在实例化的对象中,我们还可以动态地修改规则语句。
  1. // 设置获取规则
  2. $fmt = new MessageFormatter("zh_CN", "{0, number} 猴子在 {1, number} 颗树上");
  3. echo "默认规则: '" . $fmt->getPattern(), PHP_EOL; // 默认规则: '{0, number} 猴子在 {1, number} 颗树上'
  4. echo "格式化结果:" . $fmt->format(array(123, 456)), PHP_EOL; // 格式化结果:123 猴子在 456 颗树上
  5. $fmt->setPattern("{0, number} 颗树上有 {1, number} 猴子");
  6. echo "新规则: '" . $fmt->getPattern(), PHP_EOL; // 新规则: '{0, number} 颗树上有 {1, number} 猴子'
  7. echo "新规则格式化结果: " . $fmt->format(array(123, 456)), PHP_EOL; // 新规则格式化结果:123 颗树上有 456 猴子
复制代码
非常简单的两个方法,setPattern() 用于设置当前实例化对应的格式化规则,getPattern() 用于获取查察当前实例化对象的格式化规则。在设置了新规则之后,进行 format() 大概 parse() 时就是按照新的规则语句来实行的了。


格式化完整示例


上面说过,除了数字之外,还可以有日期格式的占位符,我们就来演示一下。
  1. echo MessageFormatter::formatMessage('zh_CN', '今天是 {3, date, full},当前时间为 {3, time, ::Hms}, 我要准备开始 {0} 了,今天要和 {2,number,integer} 人见面,还不能忘了要交 {1,number,currency} 元的电费', ['上班', 35.33, 25, new DateTime()]), PHP_EOL;
  2. // 今天是 2020年11月16日星期一,当前时间为 10:09:30, 我要准备开始 上班 了,今天要和 25 人见面,还不能忘了要交 ¥35.33 元的电费
复制代码
在这段语句中,我们给定的参数顺序并不是按照语句中占位符出现的顺序,如许并没有影响,只需要指定对应位置的参数数组下标即可,好比第一个 {3, date, full} 指定的就是参数数组中的第4个元素(从0开始)。date 范例、time 范例都是可以指定的范例,固然我们也可以指定它们的 日期格式 好比第二个占位符我们就只显示当前的时分秒信息。

如果是字符串信息,那么只需要一个简单的 {0} 就可以了,字符串不需要太多的范例设置。而数字范例则可以直接格式化为货币等范例,就像我们之前讲过的 NumberFormatter 中可以指定的那些范例一样。

看完这一个示例是不是就感觉到这个 MessageFormatter 的强大之处了?别急,它还有更牛X的能力。


根据参数内容进行复数显示


对于复数来说,着实中文语法中并没有如许的语句,好比说一只猫是 a cat ,两只猫是 two cats 。
  1. echo MessageFormatter::formatMessage('en_US', 'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}', [0]),PHP_EOL; // I Have no cat
  2. echo MessageFormatter::formatMessage('en_US', 'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}', [1]),PHP_EOL; // I Have a cat
  3. echo MessageFormatter::formatMessage('en_US', 'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}', [2]),PHP_EOL; // I Have 2 cats
复制代码
虽说参数范例的 plural 是复数的意思,不外着实我们可以将它看做是一个 switch() 语句的用法。
  1. echo MessageFormatter::formatMessage('zh_CN', '我{0, plural, =0{没有猫} other{有 # 只猫}}', [0]),PHP_EOL; // 我没有猫
  2. echo MessageFormatter::formatMessage('zh_CN', '我{0, plural, =0{没有猫} other{有 # 只猫}}', [1]),PHP_EOL; // 我有 1 只猫
  3. echo MessageFormatter::formatMessage('zh_CN', '我{0, plural, =0{没有猫} other{有 # 只猫}}', [2]),PHP_EOL; // 我有 2 只猫
复制代码
# 号就是对应的参数值的原内容,这一套语法又让这个 MessageFormatter 类上了一个层次吧,还有呢!我们先来看看这个题目:
  1. echo MessageFormatter::formatMessage('en_US', 'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}', [-1]),PHP_EOL; // I Have -1 cats
复制代码
参数传错了,-1 只猫可不对吧,不要紧,还有别的处置处罚方式办理这个题目。


选择条件规则

  1. // 选择表达式
  2. echo MessageFormatter::formatMessage('en_US', 'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}', [-1]),PHP_EOL; // I Have no cats
  3. echo MessageFormatter::formatMessage('en_US', 'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}', [0]),PHP_EOL; // I Have no cats
  4. echo MessageFormatter::formatMessage('en_US', 'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}', [1]),PHP_EOL; // I Have one cat
  5. echo MessageFormatter::formatMessage('en_US', 'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}', [2]),PHP_EOL; // I Have 2 cats
  6. echo MessageFormatter::formatMessage('en_US', 'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}', [10]),PHP_EOL; // I Have 10 cats
复制代码
choice 这个单词就能看出来,这是一个选择相关的语法。反面的参数着实是一个区间,分别代表 <= 0 | 1 | >=2 的范围内使用哪个内容。另外,一个占位符规则里面还可以继承套占位符号的。


总结


又大开了一回眼界。文章开头的两部门内容着实并没有什么惊喜的地方,究竟普通的字符串更换都能办到,不外越往反面但是越来越出色啊。固然,它的相关规则语法应该还有更多,只是这些资料非常少,不管是 PHP 官方文档照旧 ICU 的官方文档都没有找到过多的先容。所以我们照旧报以学习相识的态度先知道有这么回事,未来发现更风趣的资料后再来分享学习吧,也渴望有使用过的朋侪留言一起讨论哦!

到此这篇关于PHP中信息格式化操纵的文章就先容到这了,更多相关PHP中信息格式化内容请搜刮脚本之家从前的文章或继承浏览下面的相关文章渴望大家以后多多支持脚本之家!
测试代码:

github.com/zhangyue050…

参考文档:

www.php.net/manual/zh/c…

userguide.icu-project.org/formatparse…

帖子地址: 

回复

使用道具 举报

分享
推广
火星云矿 | 预约S19Pro,享500抵1000!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

草根技术分享(草根吧)是全球知名中文IT技术交流平台,创建于2021年,包含原创博客、精品问答、职业培训、技术社区、资源下载等产品服务,提供原创、优质、完整内容的专业IT技术开发社区。
  • 官方手机版

  • 微信公众号

  • 商务合作