9

Joyent Solaris サーバーでこれまで発生したことのない奇妙なバグに対処しています (localhost または同じ php 構成を持つ他の 2 つの Solaris サーバーでは発生しません)。実際、php と solaris のどちらを調べる必要があるのか​​、それがソフトウェアの問題なのかハードウェアの問題なのかはわかりません...

誰かが私たちを正しい方向に向けることができる場合に備えて、これを投稿したいだけです.

var_export()そのため、奇妙なキャラクターを扱う場合に問題があるようです。これを CLI で実行すると、localhost マシンと 2 つのサーバーで期待どおりの結果が得られますが、3 番目のサーバーでは得られません。それらはすべて で動作するように構成されていますutf-8

$ php -r "echo var_export('ñu', true);"

古いサーバーとローカルホストでこれを提供します(予想)

'ñu'

しかし、問題が発生しているサーバー ( PHP バージョン => 5.3.6 ) では、\0è、á、ç などの「一般的でない」文字が検出されるたびに null 文字が追加されます。

'' . "\0" . '' . "\0" . 'u'

どこを見るべきかについて何か考えはありますか?前もって感謝します。


より詳しい情報:

  • PHP version 5.3.6.
  • setlocale()何も解決していません。
  • default_charsetです。UTF-8_php.ini
  • mbstring.internal_encodingに設定されUTF-8ていphp.iniます。
  • mbstring.func_overload = 0.
  • これは、CLI (例) と Web アプリケーション (php-fpm + nginx) の両方で発生します。
  • iconvエンコーディングもUTF-8
  • すべてのファイルがutf-8エンコードされます。

system('locale')戻り値:

LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_ALL=

これまでに行われたいくつかのテスト (CLI):

通常の動作:

$ php -r "echo bin2hex('ñu');" => 'c3b175'
$ php -r "echo mb_strtoupper('ñu');" => 'ÑU'
$ php -r "echo serialize(\"\\xC3\\xB1\");" => 's:2:"ñ";'
$ php -r "echo bin2hex(addcslashes(b\"\\xC3\\xB1\", \"'\\\\\"));" => 'c3b1'
$ php -r "echo ucfirst('iñu');" => 'Iñu'

普通でない:

$ php -r "echo strtoupper('ñu');" => 'U' 
$ php -r "echo ucfirst('ñu');" => '?u' 
$ php -r "echo ucfirst(b\"\\xC3\\xB1u\");" => '?u' 
$ php -r "echo bin2hex(ucfirst('ñu'));" => '00b175'
$ php -r "echo bin2hex(var_export('ñ', 1));" => '2727202e20225c3022202e202727202e20225c3022202e202727'
$ php -r "echo bin2hex(var_export(b\"\\xC3\\xB1\", 1));" => '2727202e20225c3022202e202727202e20225c3022202e202727'

したがって、問題は「現在のロケールvar_export()使用するがバイト単位で動作する文字列関数」ドキュメント(@hakre の回答を参照) にあるようです。

4

5 に答える 5

6

問題のあるPHPバイナリを確認することをお勧めします。コンパイラフラグとそれが使用するライブラリを確認してください。

通常、PHPは内部でバイナリ文字列を使用します。つまり、ucfirstバイト単位で機能し、ロケールがサポートするもの(構成されている場合など)のみをサポートします。文字列型ドキュメントの詳細を参照してください。

$ php -r "echo ucfirst('ñu');" 

戻り値

?u

これは理にかなってñいます

LATIN SMALL LETTER N WITH TILDE (U+00F1)    UTF8: \xC3\xB1

PHP\xC3を別のものに変更し、UTF-8バイトシーケンスを壊して、シェルに置換文字Wikipediaを表示させるロケールを構成しました。

本当に問題を分析したい場合は、シェルや他の場所での表示方法の横にある16進ダンプから始めることをお勧めします。バイナリ文字列を明示的に定義できることを知ってくださいb"string"(これは上位互換性です。コンパイルフラグを有効にしていて、Unicodeの実験を行っていますか?)。また、文字列を文字通り書くことができます。ここではUTF-8の16進数です。

 $ php -r "echo ucfirst(b\"\\xC3\\xB1u\");"

そして、役割を果たすことができる設定はもっとたくさんあります。UTF-8で使用するPHPアプリケーションの準備への回答にいくつかのポイントをリストし始めました。


マルチバイトucfirstバリアントの例:

/**
 * multibyte ucfirst
 *
 * @param string $str
 * @param string|null $encoding (optional)
 * @return string
 */
function mb_ucfirst($str, $encoding = NULL)
{
    $first = mb_substr($str, 0, 1, $encoding);
    $rest = mb_substr($str, 1, strlen($str), $encoding);
    return mb_strtoupper($first, $encoding) . $rest;
}

mb_strtoupperドキュメントと同様にmb_convert_caseドキュメントを参照してください。

于 2012-04-14T10:17:57.807 に答える
0

私は通常utf8_encode('ñu')、すべてのフランス語の文字に使用します

于 2012-04-18T05:04:14.337 に答える
0

このための phpunit テストはhttps://gist.github.com/68f5781a83a8986b9d30に追加されています- 予想される出力がどうあるべきかを理解できるように、より良い単体テスト スイートを構築できますか?

于 2012-04-24T05:24:43.207 に答える
0

おそらくすべてのサーバーは良好な状態です。コメントの 1 つで、ucfirst() と var_export() のみに問題があると述べました。これらの応答に応じて、このSOQを見ている可能性があります。マルチバイト文字列を扱う場合、ほとんどの PHP 文字列関数は正しく動作しません。そのため、php にはそれらを処理するための別の関数セットがあります。

これは役に立つかもしれません

于 2012-04-13T20:31:51.373 に答える