首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PHP中的NumberFormatter与JS中的NumberFormat

PHP中的NumberFormatter与JS中的NumberFormat
EN

Stack Overflow用户
提问于 2019-12-09 03:23:52
回答 3查看 1.9K关注 0票数 6

在试图格式化货币时,我似乎得到了非常不一致的结果。在PHP中,我使用的是https://www.php.net/manual/en/class.numberformatter.php。我有以下演示代码:

代码语言:javascript
运行
复制
$number = 5125.99;
echo getInternationallyFormattedCurrency($number, 'tl-PH', 'PHP');
echo '<br/>';
echo getInternationallyFormattedCurrency($number, 'fil-PH', 'PHP');
echo '<br/>';
echo getInternationallyFormattedCurrency($number, 'en-US', 'PHP');
echo '<br/>';
echo '<br/>';
echo getInternationallyFormattedCurrency($number, 'tl_PH', 'USD');
echo '<br/>';
echo getInternationallyFormattedCurrency($number, 'fil_PH', 'USD');
echo '<br/>';
echo getInternationallyFormattedCurrency($number, 'en_US', 'USD');
echo '<br/>';

当我在本地主机上运行它(是PHP版本7.3.7,但我更新以匹配服务器的PHP7.3.12-ICU版本64.2)时,我得到如下信息:

代码语言:javascript
运行
复制
₱5,125.99
₱5,125.99
PHP 5,125.99

$5,125.99
$5,125.99
$5,125.99

但是,当我在服务器上运行它(PHP7.3.12-ICU版本4.2.1)时,我得到了以下内容:

代码语言:javascript
运行
复制
₱ 5125.99
₱ 5125.99
₱5,125.99

$ 5125.99
$ 5125.99
$5,125.99

为什么会有这种区别?哪一个是正确的?我猜我的本地机器是因为更高的ICU版本?

我也需要来自JS的完全相同的功能。因此,在对象/NumberFormat上,我放置了以下等价代码:

代码语言:javascript
运行
复制
var number = 5125.99;

console.log(new Intl.NumberFormat('tl-PH', { style: 'currency', currency: 'PHP' }).format(number));
console.log(new Intl.NumberFormat('fil-PH', { style: 'currency', currency: 'PHP' }).format(number));
console.log(new Intl.NumberFormat('en-US', { style: 'currency', currency: 'PHP' }).format(number));
console.log(new Intl.NumberFormat('tl-PH', { style: 'currency', currency: 'USD' }).format(number));
console.log(new Intl.NumberFormat('fil-PH', { style: 'currency', currency: 'USD' }).format(number));
console.log(new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(number));

我明白了:

代码语言:javascript
运行
复制
> "PHP 5,125.99"
> "₱5,125.99"
> "PHP 5,125.99"
> "$5,125.99"
> "$5,125.99"
> "$5,125.99"

所以-这是另一个结果。我需要一种方法来格式化PHP之间的货币一致性。我该怎么做?

更新1:

我的本地机器的ICU版本是64.2,而我的服务器是4.2.1。我会看看我的主机提供商是否能将ICU版本更新为最新版本。这可能解释了我的本地机器输出和服务器输出之间的差异。

仍然不确定为什么JS的行为会有所不同。

更新2:

我的托管公司说,由于cPanel,我需要坚持ICU版本4.2.1。尽管cPanel有一些关于如何升级ICU版本的提示,但显然不建议这样做。

更新3:

我现在想让我的JS对一个处理数字格式化的PHP方法进行Ajax调用,这样我就可以确定我得到了相同的格式输出。不过,这感觉是一种缓慢而昂贵的解决方案。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-12-15 16:39:49

我试过这种方法:

代码语言:javascript
运行
复制
<?php

function process($locale, $value, $currency){
    $fmt = numfmt_create($locale, NumberFormatter::CURRENCY );
    echo "Locale: $locale, Currency: $currency, Result: " . $fmt->formatCurrency($value, $currency) . "\n";
}

$locales = ["tl_PH","fil_PH", "en_US"];
$currencies = ["USD", "PHP"];
$value = 5125.99;

foreach ($locales as $locale){
    foreach ($currencies as $currency){
        process($locale, $value, $currency);
    }
}

得到了一致的结果:

代码语言:javascript
运行
复制
Locale: tl_PH, Currency: USD, Result: $5,125.99
Locale: tl_PH, Currency: PHP, Result: ₱5,125.99
Locale: fil_PH, Currency: USD, Result: $5,125.99
Locale: fil_PH, Currency: PHP, Result: ₱5,125.99
Locale: en_US, Currency: USD, Result: $5,125.99
Locale: en_US, Currency: PHP, Result: PHP 5,125.99

因此,为了100%的安全,我建议为格式化目的创建一个小的服务器端组件,这样您就可以传递区域设置、值和货币,并且总是有相同的结果,而不管它的后端还是前端需要格式化的字符串。

另外,请注意,tl-PHtl_PH并不相同。始终如一地使用tl_PHfil_PHen_US

票数 1
EN

Stack Overflow用户

发布于 2019-12-18 06:43:20

从php的角度来看,由于php依赖底层C库,这是不一致的地方(编译时):

关于不同格式的说明实际上并不取决于PHP,而取决于针对编译的PHP库的版本,因为该库有一个数据库,其中包含针对不同地区的格式化规则。https://www.php.net/manual/en/numberformatter.formatcurrency.php#116984

在php中没有什么可做的,我们必须格外关注这个问题。

下面是一些自己测试的注意事项!

这些片段返回格式化的数字(不返回科学表示法),但是是舍入,这是不需要的。它照顾成群结队的数千人,我们可以选择是否显示。在我看来,这是个坏主意,想要避开他们。

javascript中,有有很多选择

代码语言:javascript
运行
复制
var number = 5125.9566654332455556679;

console.log("\n",
  number.toLocaleString('fil-PH', {maximumFractionDigits:5, style:'currency', currency:'PHP', useGrouping:true})
  ,"\n",
  number.toLocaleString('fil-PH', {maximumFractionDigits:5, style:'currency', currency:'PHP', useGrouping:false})
  ,"\n",
  number.toLocaleString('fullwide', {maximumFractionDigits:5, style:'currency', currency:'USD', useGrouping:true})
  ,"\n",
  number.toLocaleString('fullwide', {maximumFractionDigits:5, style:'currency', currency:'USD', currencyDisplay:'symbol', useGrouping:false})

)

样本输出:

代码语言:javascript
运行
复制
 ₱5,125.95667 
 ₱5125.95667 
 $5,125.95667 
 $5125.95667

支持代码列表

php中,为了获得类似的东西,我发现对符号更容易使用关联数组。代码在所有地方都是一样的。

代码语言:javascript
运行
复制
<?php
$number = 5125.9566654332455556679;

$a = new \NumberFormatter("en-US", \NumberFormatter::CURRENCY);
$a = new \NumberFormatter("tl-PH", \NumberFormatter::CURRENCY);
echo $a->format($number);  

echo PHP_EOL;

$symbols = (object)["PHP"=>"₱", "USD"=>"$"];
$precision = 5;

echo number_format($number,$precision,'.','');
echo PHP_EOL;

echo $symbols->PHP . number_format($number,$precision);
echo PHP_EOL;

echo $symbols->USD . number_format($number,$precision,'.','');
echo PHP_EOL;

样本输出注意使用NumberFormatter()的四舍五入。在大多数情况下,它是不需要的,只使用格式()更灵活。

代码语言:javascript
运行
复制
₱5,125.96
5125.95667
₱5,125.95667
$5125.95667
票数 1
EN

Stack Overflow用户

发布于 2019-12-17 06:19:09

只是一个主意..。但是为了在两种不同的语言中得到一致的结果,我建议使用完全相同的库代码。

如果您使用https://github.com/phpv8/v8js在PHP上运行Intl.NumberFormat怎么办?这里还有一个例子,https://github.com/phpv8/v8js/issues/182

我可能会沿着这条路走,让一切都保持一致。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59242134

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档