38

私は自分のスクリプトでちょうどいいUTF-8文字を使うことができます。

実際のところ、それは可能です変数名と関数名にUnicode文字が含まれている

もありますmb_string拡張子これはマルチバイト文字列を扱いますが、それでも数え切れないほどの記事でPHPはUnicodeサポートの欠如について批判されています。

わかりません。なぜPHPはUnicodeをサポートしていないと言われているのですか?

7 답변


39

PHPが数年前に開始されたとき、UTF-8は本当にサポートされていませんでした。私たちは、Windows 98 / Meのような非Unicode OSがまだ最新の時代であり、Delphiのような他の大きな言語も非Unicodeであった時代について話しています。すべての言語が初日からUnicodeを念頭に置いて設計されているわけではありません。多くのものを壊さずに完全にあなたの言語をUnicodeに変更することは困難です。たとえば、Delphiは1年か2年前にUnicode互換になりましたが、JavaやC#などの他の言語は1日目からUnicodeで設計されました。

したがって、PHPが成長してPHP 3、PHP 4、そして今ではPHP 5になったとき、誰もUnicodeを追加することにしませんでした。どうして?おそらく既存のスクリプトとの互換性を保つためか、utf8_de / encodeとmb_stringが既に存在していて動作しているためです。よくわかりませんが、それが有機的成長と関係があると強く信じています。機能は単にデフォルトでは存在しません。それらは誰かによって書かれなければなりません、そしてそれはまだPHPにはまだ起こりませんでした。

編集:わかりました、私は質問を間違って読んだ。問題は、文字列はどのように内部に格納されるのかということです。 「Währung」または「Écriture」と入力した場合、使用されるバイトの作成にどのエンコーディングが使用されますか? PHPの場合、コードページ付きのASCIIです。つまり、ISO-8859-15を使用して文字列をエンコードし、それを中国語のコードページでデコードすると、奇妙な結果になります。代替手段は、すべてがUnicodeとして格納されているC#やJavaなどの言語です。つまり、コードページがなくなり、理論的には混乱することはありません。私はお勧めジョエルの記事文字列はどのように内部的に格納されているのか、そしてPHPでの答えは "Not in Unicode"です。つまり、常に文字列を処理するために文字列を処理するときは注意深く、明示的にする必要があります。入力、格納(データベース)、および出力中は、文字列を適切なエンコーディングで保存してください。


  • それは私が求めていたものではありません。 PHPがUnicodeと互換性がないのはどのような要素ですか? - moo
  • ここで死んだ馬を倒したくはありませんが、" PHP 6では_____"となります。何年も前からよくあることです。いやらしいことが出るのはいつですか。古いphpコードがとても一般的になった今では、それが広く採用されるようになるでしょうか? - TM.
  • PHP 5も同じ問題を抱えていました。そのためまだ何人かの人々がphp 4を実行しています(実際に私自身のWebHostはデフォルトでPHP 4を使います。 ) PHP 6がついに登場すると、採用が大きくなるまでには確かに長い時間がかかります。 - Michael Stum
  • 私はあなたがPHPを後ろ向きにしていてまだUnicodeを適切にサポートしていないと主張するJoelの記事にリンクしているのを気に入っています - そして彼はそれを2003年に書きました! - MarkJ
  • また見なさいこの質問。 - tchrist

34

技術的な問題ではなく、主に文化的な問題だと思います。

技術的な問題に関して、そして '1文字は1バイトに等しい'という仮定に基づいて構築されたエコシステムにUnicodeを実装することは、実に自明なことではありません。 2001年頃からきちんとしていて主に働いているUnicodeの互換性がありますが)。

読んだときphpの最新の公式ドキュメントに添付されているディスカッションスレッドutf8_encode()関数、めまいがする。

最初に、その関数が呼び出されますutf8_encode();しかしながら、ドキュメントはそれが期待する文字列がISO-8859-1(別名latin-1)にあると予想されると述べています。それはsooo phpです、それはsooo 80年代です。

ほとんどのコメント投稿者は、Unicodeを負担と見なしているようです。 「未知の内容の」文字列を変換する方法、混合エンコーディングを含む文字列を処理する方法(wtf?)、またはその関数の4バイトあたり4バイトを超えるために通常は破損するコードポイントの処理方法が多数あります。コードポイントの制限

議論は波紋を取り除くために、またはその関数の動作の問題のある部分を避けるためにfixupsを中心にしています。それは、私にとっては、すごいphpです:みんながただ修正をしているだけで、基本的に正しい方法で実装されていることはほとんどありません。あなたがこれが私の側に中傷的であると信じるならば、ここにいくつかのちょっとしたことがあります:

文書がすでにUTF-8である場合、これはドイツ語のウムラウト語[äöü]を破るようです。

(utf-8が2回適用されたときに動作するようには設計されていないことを理解できない)

iconv()関数を見てください。これは8859から1252に変換してUTF8に変換する方法を提供します。

(良い点:php開発者の一部での先行技術の無視、代わりにバグのある自身の実装)

utf8_encodeが必要かどうかを検出するためのpreg_matchの使用[...]代理を除く[...]

(問題のあるすべてのコンテンツを文字列から黙って削除し、破損しないものだけを残すように提案するutf8_encode();これはテキストを判読不能にする(あるいは完全に消える)かもしれませんが、ちょっと、これ以上エラーメッセージはありません)

まだUTF-8ではない場合にのみ文字列をエンコードする[...]mb_detect_encoding($s, "UTF-8")

(指摘したように他のコメンターによるこれはうまくいきません。

$str = 'áéóú'; // ISO-8859-1
mb_detect_encoding($str, 'UTF-8'); // 'UTF-8'
mb_detect_encoding($str, 'UTF-8', true); // false

そのため、ここでは、あるバグが別のバグに置き換えられているのを見ています。ハッピーハンティング。また、彼らがここで提案しているのは、ヒューリスティック(遅い、不確実な)手段を使って問題を解決することです。

ドキュメントにあるように、utf8_ [encode | decode]は、ISO-8859-1から/への変換ではなく、windows-1252文字への変換も行います。

(あなたは、公式のphp文書を明確で網羅的にすることに頼ることはできません。あなたは常に何年ものユーザー経験を通読しなければなりません。

私はis_utf8関数に取り組んでいて、他に加えてここにそれを投稿したいと思いました。

(Unicodeが適切に実装されていないために主にのみ存在する問題に対する修正。utf8_encode()関数はコードポイントあたり4バイトを超えてあきらめます、結果の(または出力?)テキストが5000文字の制限を超えると、それはまた壊れます)

私はこのようにして行くことができます。このスレッドから判断すると、phpコミュニティは、エンコーディングと文字セットがすべて何であるか、一般的には健全なインフラストラクチャを構築するために必要なことを把握する準備ができているようには思えません。 Unicodeを適切な方法で実装してください。代わりに、足場、段ボール、釘、ハンマーを使ってphpと呼ばれるこの壮大な建物を建設し、他の釘では元に戻せないような問題が発生するたびにダクトテープを貼っていきます。もちろん、その建物は時折起こる合法だが予想外の性質のように、吹くすべての風に苦しむでしょう。

この特定のスレッドが8年間アクティブであることを見ても、状況が今から8年間でさらに良くなるとは限らないという確信が得られません。


  • +1とても読みました。 THX。 - aefxx
  • あなたの答えは偏って見えるかもしれませんが、あなたは確かにいくつかの良い点を挙げています。 PHP開発者からの+1。 - Cmorales

11

「マルチバイト文字」の概念は、問題の中心にあります。

  1. 実装の詳細が漏れる:実装者がどのようにデータを表現するかを知らなくても、文字の抽象化を扱うことができるはずです - おそらくプラットフォームによっては、すべてをUTF16またはUTF32として表現するのに適しています。マルチバイトではなく、文字抽象化のユーザーは気にする必要があります。
  2. これは問題です。文字列がバイトシーケンスであることを「知っている」という古くからの考えの習慣に加えて、バイトがUnicode文字と呼ばれるものにまとまっていることを知っておく必要があります。それに対処するために至る所で事件。
  3. それは象を食べようとしているマウスのようなものです。 UnicodeをASCIIの拡張としてフレーミングすることにより(私たちは普通の文字列を持ち、mb_stringsを持ちます)、それは間違ったやり方で物事を回避し、1バイト以上を必要とする面白い波紋を持つ文字を扱うのに特別なケースが必要です。 Unicodeを必要な文字のための抽象スペースを提供するものとして扱う場合、ASCIIは特別な場合として扱う必要なしにそれに対応します。


5

あなたはそれを自分で言います:マルチバイト文字を含む文字列を正しく扱うためには、拡張子を使う必要があります。より一般的な「通常の」拡張機能の代わりに拡張機能を使用することをどこかに忘れて、あなたのデータは断片化されます。どこでも拡張機能を使用するように更新されていないサードパーティのライブラリを使用する場合も同じことが起こります。

また、非常に人気のあるエンコーディングまだ明示的ですではないPHPでサポートされています。おそらくそれは不可能で、下位互換性を保つことは不可能だからです。


3

一般的な拡張機能の多くはUnicodeをサポートしていないか、あるいは(さらに悪いことに)XMLReaderのように、文字列にUnicode / utf-8のシーケンスが含まれていることを「知る必要がある」のです。そしてそれは、PHPのglob()がwin32でFindFirstFileAまたはFindFirstFileWを呼び出すことによって、かなりの違いを生み出すことができます。

もう1つの(はるかに小さいが驚くほど頻繁に煩わしさの原因となる)問題は、PHPが認識しないBOMです。


3

文字列関数の多くは、Cライブラリと同等のものを囲む単なる薄いラッパーです。これも、すべてをバイトのシーケンスとして扱います。もう1つの理由は、PHPは多くの不必要な下位互換性のある手荷物を持ち歩いているため、3& 4の悪い設計上の決定にとどまることです。

たぶん5.3の名前空間で、彼らはついに古い関数を段階的に廃止する方法を持つでしょう。


2

「サポート」とは、「ネイティブサポート」のことです。を見てみましょうこの詳細な情報を入手する。


  • その記事は4年近く前のものです - 正確な情報は今のところほとんどありません。 - postfuturist
  • ポストフューチャリスト、その記事は今ではほぼ6歳で、ほとんど変わっていないようです。 - flow

リンクされた質問


関連する質問

最近の質問