10

ローカライズされた通貨文字列を通貨と浮動小数点値に解析しようとしています。

しばらくはすべてがうまく機能しますが、現在、いくつかの問題が発生しています。NumberFormatter::parseCurrency は追加の非表示文字を使用しているようです:

テストコード:

<?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 で等しく出力されることです...

助言がありますか?前もって感謝します

編集1:

作業値の 16 進ダンプ:

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

非動作値の 16 進ダンプ:

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

編集2:

使用されているホワイトスペースに問題があるようです。c2 a0 は NO-BREAK SPACE であり、(おそらく?) NumberFormatter::parseCurrency() によって必要とされます。ただし、0x20 はデフォルトのスペースです (入力フォームに入力されます)。現在の回避策は、空白を NO-BREAK SPACE に置き換えることです$value = str_replace("\x20", "\xC2\xA0", $value);

編集3:

別のシステム (Zend Server 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 €"
}

編集4:

スペースを使用する場合と非ブレーク スペース構成を使用する場合の主な違いは、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
4

1 に答える 1

3

NumberFormatter::parseCurrencyICU ライブラリ関数の薄いラッパーですunum_parseDoubleCurrency(ソースを参照)。

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 €」を自分で入力している場合、空白の問題だけでなく、さらに多くの問題が発生する可能性があります。そうは言っても、言及した回避策(に置き換える\x20\xc2\xa0は、使用したい場合に対処する唯一の方法ですNumberFormatter

于 2013-05-12T16:07:51.850 に答える