IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 学习PHP中的信息格式化操作 -> 正文阅读

[PHP知识库]学习PHP中的信息格式化操作

学习PHP中的信息格式化操作

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

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

格式化

//?格式化
$fmt?=?new?MessageFormatter("zh_CN",?"{0,number,integer}?只猴子在?{1,number,integer}?颗树上,每只树上有?{2,number}?只猴子");
echo?$fmt->format([4560,?123,?4560?/?123]),?PHP_EOL;
//?4,560?只猴子在?123?颗树上,每只树上有?37.073?只猴子

$fmt?=?new?MessageFormatter("de",?"{0,number,integer}?Affen?auf?{1,number,integer}?B?umen?sind?{2,number}?Affen?pro?Baum");
echo?$fmt->format([4560,?123,?4560?/?123]),?PHP_EOL;
//?4.560?Affen?auf?123?B?umen?sind?37,073?Affen?pro?Baum

echo?MessageFormatter::formatMessage("zh_CN",?"{0,number,integer}?只猴子在?{1,number,integer}?颗树上,每只树上有?{2,number}?只猴子",?[4560,?123,?4560?/?123]),?PHP_EOL;
//?4,560?只猴子在?123?颗树上,每只树上有?37.073?只猴子

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;
//?4.560?Affen?auf?123?B?umen?sind?37,073?Affen?pro?Baum

看到了吗?类似于 PDO 里预编译操作的占位符。在调用 format() 方法后,就可以让这个方法里面的参数来替换占位符的内容。我们可以指定占位的所使用的参数类型和位置,{参数下标,类型,扩展类型} 这就是这个信息数据格式化的占位符的规则定义。看起来貌似很简单呀,其实它还有更多的功能,我们将在后面看到。不过需要注意的是,它只支持数字、日期、文本片段类型,文章最后的参考链接中有官方的文档可以查阅。

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

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

能够进行格式化,当然我们也能够根据语句规则来反格式化相关的字符串从而获得对应占位符的参数列表。

//?根据格式化规则反向获取规则参数
$fmt?=?new?MessageFormatter('zh_CN',?"{0,number,integer}?只猴子在?{1,number,integer}?颗树上,每只树上有?{2,number}?只猴子");
$res?=?$fmt->parse("4,560?只猴子在?123?树上,每只树上有?37.073?只猴子");
var_export($res);?//?false
echo?"ERROR:?"?.?$fmt->getErrorMessage()?.?"?("?.?$fmt->getErrorCode()?.?")\n";
//?ERROR:?Parsing?failed:?U_MESSAGE_PARSE_ERROR?(6)

$fmt?=?new?MessageFormatter('en_US',?"{0,number,integer}?monkeys?on?{1,number,integer}?trees?make?{2,number}?monkeys?per?tree");
$res?=?$fmt->parse("4,560?monkeys?on?123?trees?make?37.073?monkeys?per?tree");
var_export($res);
//?array?(
//?????0?=>?4560,
//?????1?=>?123,
//?????2?=>?37.073,
//???)

$fmt?=?new?MessageFormatter('de',?"{0,number,integer}?Affen?auf?{1,number,integer}?B?umen?sind?{2,number}?Affen?pro?Baum");
$res?=?$fmt->parse("4.560?Affen?auf?123?B?umen?sind?37,073?Affen?pro?Baum");
var_export($res);
//?array?(
//?????0?=>?4560,
//?????1?=>?123,
//?????2?=>?37.073,
//???)

$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");
var_export($fmt);
//?array?(
//?????0?=>?4560,
//?????1?=>?123,
//?????2?=>?37.073,
//???)

使用实例化后的 parse() 方法或者直接使用静态方法 MessageFormatter::parseMessage() 就能够实现这样的操作。需要注意的是,对于 zh_CN ,也就是中文语言区域设置来说,这个操作是会出问题的。通过 getErrorMessage() 和 getErrorCode() 就可以看到错误信息以及错误代码,可以看到对于中文来说,直接返回的错误信息就是解析失败。

设置获取规则

在实例化的对象中,我们还可以动态地修改规则语句。

//?设置获取规则
$fmt?=?new?MessageFormatter("zh_CN",?"{0,?number}?猴子在?{1,?number}?颗树上");
echo?"默认规则:?'"?.?$fmt->getPattern(),?PHP_EOL;?//?默认规则:?'{0,?number}?猴子在?{1,?number}?颗树上'
echo?"格式化结果:"?.?$fmt->format(array(123,?456)),?PHP_EOL;?//?格式化结果:123 猴子在 456 颗树上

$fmt->setPattern("{0,?number}?颗树上有?{1,?number}?猴子");
echo?"新规则:?'"?.?$fmt->getPattern(),?PHP_EOL;?//?新规则:?'{0, number}?颗树上有?{1, number}?猴子'
echo?"新规则格式化结果:?"?.?$fmt->format(array(123,?456)),?PHP_EOL;?//?新规则格式化结果:123 颗树上有 456 猴子

非常简单的两个方法,setPattern() 用于设置当前实例化对应的格式化规则,getPattern() 用于获取查看当前实例化对象的格式化规则。在设置了新规则之后,进行 format() 或者 parse() 时就是按照新的规则语句来执行的了。

格式化完整示例

上面说过,除了数字之外,还可以有日期格式的占位符,我们就来演示一下。

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;
//?今天是?2020年11月16日星期一,当前时间为?10:09:30,?我要准备开始?上班?了,今天要和?25?人见面,还不能忘了要交?¥35.33?元的电费

在这段语句中,我们给定的参数顺序并不是按照语句中占位符出现的顺序,这样并没有影响,只需要指定对应位置的参数数组下标即可,比如第一个 {3, date, full} 指定的就是参数数组中的第4个元素(从0开始)。date 类型、time 类型都是可以指定的类型,当然我们也可以指定它们的 日期格式 比如第二个占位符我们就只显示当前的时分秒信息。

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

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

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

对于复数来说,其实中文语法中并没有这样的语句,比如说一只猫是 a cat ,两只猫是 two cats 。

echo?MessageFormatter::formatMessage('en_US',?'I?Have?{0,?plural,?=0{no?cat}?=1{a?cat}?other{#?cats}}',?[0]),PHP_EOL;?//?I?Have?no?cat
echo?MessageFormatter::formatMessage('en_US',?'I?Have?{0,?plural,?=0{no?cat}?=1{a?cat}?other{#?cats}}',?[1]),PHP_EOL;?//?I?Have?a?cat
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() 语句的用法。

echo?MessageFormatter::formatMessage('zh_CN',?'我{0,?plural,?=0{没有猫}?other{有?#?只猫}}',?[0]),PHP_EOL;?//?我没有猫
echo?MessageFormatter::formatMessage('zh_CN',?'我{0,?plural,?=0{没有猫}?other{有?#?只猫}}',?[1]),PHP_EOL;?//?我有?1?只猫
echo?MessageFormatter::formatMessage('zh_CN',?'我{0,?plural,?=0{没有猫}?other{有?#?只猫}}',?[2]),PHP_EOL;?//?我有?2?只猫

# 号就是对应的参数值的原内容,这一套语法又让这个 MessageFormatter 类上了一个层次吧,还有呢!我们先来看看这个问题:

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 只猫可不对吧,没关系,还有别的处理方式解决这个问题。

选择条件规则

//?选择表达式
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
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
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
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
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 的官方文档都没有找到过多的介绍。所以我们还是报以学习了解的态度先知道有这么回事,将来发现更有趣的资料后再来分享学习吧,也希望有使用过的朋友留言一起讨论哦!

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/5.PHP中针对区域语言标记信息的操作.php

参考文档:

https://www.php.net/manual/zh/class.messageformatter.php

http://userguide.icu-project.org/formatparse/messages

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:19:19  更:2021-07-10 14:21:07 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 16:32:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码