2013-05-08 62 views
9

我想解析本地货币字符串货币和浮动值。如何更改NumberFormatter :: parseCurrency()接受空白和非破坏空间的行为?

一切运作良好一段时间,现在我们遇到一些问题。看来的NumberFormatter :: parseCurrency使用一个额外的不可见字符:

Testcode:

<?php 
$formatter = new NumberFormatter("de_DE", NumberFormatter::CURRENCY); 
var_dump(array(
    $formatter->parseCurrency("88,22 €", $curr), // taken from output of $formatter->format(88.22) 
    $formatter->parseCurrency("88,22 €", $curr), // input with keyboard 
    $formatter->parseCurrency("88,22 \xE2\x82\xAc", $curr), // just a test 
    $formatter->format(88.22), 
    "88,22 €" // keyboard input 
)); 

输出:

array(5) { 
    [0]=> float(88,22) 
    [1]=> bool(false) 
    [2]=> bool(false) 
    [3]=> string(10) "88,22 €" // this as input works 
    [4]=> string(9) "88,22 €" // this not... 
} 

正如你所看到的,有在输出3的字符串长度的差异和4.

我在PHP 5.3(启用了mbstring的ubuntu)和5.4(在Mac OS X上的Zend Server)上得到了相同的结果。

的主要问题是,从我的形式(ZF1应用程序)输入值同样与指数4个输出...

有什么建议?在此先感谢

EDIT1:

工作价值的hexdump都:

00000000 38 38 2c 32 32 c2 a0 e2 82 ac 0a     |88,22......| 
0000000b 

hexdump都非工作值:

00000000 38 38 2c 32 32 20 e2 82 ac 0a     |88,22 ....| 
0000000a 

EDIT2:

这似乎是使用白色皮肤的问题。 c2 a0是NO-BREAK SPACE和NumberFormatter :: parseCurrency()所需的(可能?)。但0x20是默认空间(在输入表单中输入)。 当前的解决办法与$value = str_replace("\x20", "\xC2\xA0", $value);

EDIT3替换为NO-BREAK SPACE的空白:

在另一个系统(与Zend服务器5.6,Mac OS X的MBSTRING启用,PHP 5.3.14)一切正常:

array(5) { 
    [0]=> float(88,22) 
    [1]=> float(88,22) 
    [2]=> float(88,22) 
    [3]=> string(9) "88,22 €" 
    [4]=> string(9) "88,22 €" 
} 

Edit4:

与S工作之间的主要区别节奏和非休息空间配置工作是ICU版本:

工作版本:

intl 

Internationalization support => enabled 
version => 1.1.0 
ICU version => 3.8.1 

Directive => Local Value => Master Value 
intl.default_locale => no value => no value 
intl.error_level => 0 => 0 

不工作的版本:

intl 

Internationalization support => enabled 
version => 1.1.0 
ICU version => 4.8.1.1 
ICU Data version => 4.8.1 

Directive => Local Value => Master Value 
intl.default_locale => no value => no value 
intl.error_level => 0 => 0 
+1

只是一个想法:格式化程序UTF-8编码(0x20AC)和键盘Latin-1(0x80)中的€符号?据我所知strlen()函数不知道Unicode字符。如果它由var_dump()内部使用,那将解释附加字符。 – CodeZombie 2013-05-08 10:54:13

+0

我的终端应用程序(iTerm2)使用Unicode(UTF-8)作为终端仿真。此外,这种错误/行为发生在浏览器通过html表单文本输入字段的输入数据中。为了澄清,我添加了hexdump输出。 – nofreeusername 2013-05-08 11:05:45

+0

是保存为UTF-8的文件吗? – 2013-05-09 16:23:22

回答

3

NumberFormatter::parseCurrency是围绕ICU库函数unum_parseDoubleCurrency瘦包装( see source)。

ICU库的功能是限制性的,因为它只会解析由双功能unum_formatDoubleCurrency产生的字符串。该格式由Unicode区域设置数据驱动,该数据指定货币值与数值之间的非间隔空格。很明显,早期版本的库接受了其他空白字符。

总之,您不能让NumberFormatter::parseCurrency接受空格。然而,Zend_Currency也应该输出不间断空格默认:

$currency = new Zend_Currency(array(
    'currency' => 'EUR', 
    'value' => 88.22, 
), 'de_DE'); 

var_dump(
    strval($currency),    // 88,22 € 
    strpos($currency, "\x20"),  // false 
    strpos($currency, "\xc2\xa0") // 5 
); 

的问题是,您的应用程序的一部分,输出空间,如何解决这个问题。你提到它是你的表单的一部分,所以也许你可以看看让表单返回货币和价值作为单独的领域,所以你不必担心解析数字。如果用户自己输入字符串“88,22€”,则可能会遇到更多问题,而不仅仅是空白问题。话虽如此,你提到的解决方法(用\xc2\xa0代替\x20)是解决这个问题的唯一方法,如果你想使用NumberFormatter

+0

thx的解释! Zend_Currency返回正确的值。但是我的表单允许直接用户输入带浮点的货币符号的本地格式。 Zend Framework的完整解决方案是添加到元素的自定义过滤器,因为这对NumberFormatter或pecl-intl来说不是真正的问题。 – nofreeusername 2013-05-13 18:58:10