ずっとUTF-8

1228
mercutio 2008-11-11 11:04.

新しいサーバーをセットアップしていて、WebアプリケーションでUTF-8を完全にサポートしたいと考えています。私は過去に既存のサーバーでこれを試しましたが、常にISO-8859-1にフォールバックする必要があるようです。

エンコーディング/文字セットを正確にどこに設定する必要がありますか?これを行うには、Apache、MySQL、およびPHPを構成する必要があることを認識しています。従うことができる標準のチェックリストがありますか、または不一致が発生する場所のトラブルシューティングを行うことができますか?

これは、MySQL 5、PHP、5、およびApache2を実行する新しいLinuxサーバー用です。

16 answers

1044
chazomaticus 2008-11-11 11:43.

データストレージ

  • utf8mb4データベース内のすべてのテーブルとテキスト列に文字セットを指定します。これにより、MySQLはUTF-8でネイティブにエンコードされた値を物理的に格納および取得します。照合順序が指定されているutf8mb4場合utf8mb4_*(明示的な文字セットなしで)、MySQLは暗黙的にエンコーディングを使用することに注意してください。

  • 古いバージョンのMySQL(<5.5.3)では、残念ながらutf8、Unicode文字のサブセットのみをサポートする単純なを使用する必要があります。冗談だったらいいのに。

データアクセス

  • アプリケーションコード(PHPなど)では、使用するDBアクセス方法に関係なく、接続文字セットをに設定する必要がありますutf8mb4。このように、MySQLは、データをアプリケーションに渡したり、その逆を行ったりするときに、ネイティブUTF-8からの変換を行いません。

  • 一部のドライバーは、接続文字セットを構成するための独自のメカニズムを提供します。これは、独自の内部状態を更新し、接続で使用されるエンコードをMySQLに通知します。これは通常推奨されるアプローチです。PHPの場合:

    • PHP≥5.3.6でPDO抽象化レイヤーを使用している場合charsetは、DSNで次のように指定できます。

       $dbh = new PDO('mysql:charset=utf8mb4');
      
    • mysqliを使用している場合は、次のように呼び出すことができますset_charset()

        $mysqli->set_charset('utf8mb4');       // object oriented style
        mysqli_set_charset($link, 'utf8mb4');  // procedural style
      
    • プレーンなmysqlで立ち往生しているが、PHP≥5.2.3を実行している場合は、を呼び出すことができますmysql_set_charset

  • ドライバが接続文字セットを設定するための独自のメカニズムを提供していない場合は、クエリを発行して、アプリケーションが接続上のデータがエンコードされることをどのように期待するかをMySQLに通知する必要がありますSET NAMES 'utf8mb4'

  • utf8mb4/に関する同じ考慮事項が上記と同じutf8ように適用されます。

出力

  • アプリケーションが他のシステムにテキストを送信する場合は、文字エンコードについても通知する必要があります。Webアプリケーションでは、データが送信されるエンコーディングをブラウザに通知する必要があります(HTTP応答ヘッダーまたはHTMLメタデータを介して)。

  • PHPでは、default_charsetphp.iniオプションを使用するかContent-Type、自分でMIMEヘッダーを手動で発行できます。これは手間がかかりますが同じ効果があります。

  • を使用して出力をエンコードする場合は、2番目のパラメーターとしてjson_encode()追加JSON_UNESCAPED_UNICODEします。

入力

  • 残念ながら、受信したすべての文字列を保存したり、どこでも使用したりする前に、有効なUTF-8であることを確認する必要があります。PHPmb_check_encoding()がそのトリックを実行しますが、それを忠実に使用する必要があります。悪意のあるクライアントは任意のエンコーディングでデータを送信できるため、これを回避する方法は実際にはありません。PHPにこれを確実に実行させるためのトリックは見つかりませんでした。

  • 現在のHTML仕様を読んだところ、次のサブ箇条書きは不要であるか、最新のHTMLではもはや有効ではありません。私の理解では、ブラウザはドキュメントに指定された文字セットでデータを処理して送信します。ただし、古いバージョンのHTML(XHTML、HTML4など)をターゲットにしている場合は、次の点が役立つ場合があります。

    • HTML5より前のHTMLの場合のみ:ブラウザーから送信されるすべてのデータをUTF-8にする必要があります。残念ながら、これを確実に行う唯一の方法は、accept-charsetすべての<form>タグに属性を追加することです<form ... accept-charset="UTF-8">
    • HTML5より前のHTMLの場合のみ:W3C HTML仕様では、クライアントはデフォルトでサーバーが提供する文字セットでフォームをサーバーに返送する必要があると規定されていますが、これは明らかに推奨事項にすぎないため、すべての文字を明示する必要があります。<form>鬼ごっこ。

その他のコードに関する考慮事項

  • 当然のことながら、提供するすべてのファイル(PHP、HTML、JavaScriptなど)は、有効なUTF-8でエンコードする必要があります。

  • UTF-8文字列を処理するたびに、安全に処理することを確認する必要があります。残念ながら、これは難しい部分です。PHPのmbstring拡張機能を多用したいと思うかもしれません。

  • PHPの組み込み文字列操作は、デフォルトではUTF-8で安全ではありません通常のPHP文字列操作(連結など)で安全に実行できることがいくつかありますが、ほとんどの場合、同等のmbstring関数を使用する必要があります。

  • 何をしているのかを知るには(読んでください:混乱させないでください)、UTF-8とそれが可能な限り低いレベルでどのように機能するかを本当に知る必要があります。あなたが知る必要があるすべてを学ぶためのいくつかの良いリソースについては、utf8.comからのリンクのいずれかをチェックしてください。

157
mercator 2008-11-13 09:27.

chazomaticusの優れた答えに1つ追加したいと思います:

METAタグも忘れないでください(このように、またはHTML4またはXHTMLバージョンのように):

<meta charset="utf-8">

それは些細なことのように思えますが、IE7は以前にそれに関する問題を私に与えました。

私はすべてを正しくやっていた。データベース、データベース接続、およびContent-Type HTTPヘッダーはすべてUTF-8に設定されており、他のすべてのブラウザーでも正常に機能しましたが、InternetExplorerは依然として「西ヨーロッパ」エンコーディングの使用を主張していました。

ページにMETAタグがないことが判明しました。それを追加することで問題は解決しました。

編集:

W3Cには、実際にはI18N専用のかなり大きなセクションがあります。この問題に関連する記事が多数あります。HTTP、(X)HTML、CSSの側面について説明しています。

  • FAQ:(X)HTMLページのエンコーディングをUTF-8に変更する
  • HTMLでの文字エンコードの宣言
  • チュートリアル:XHTML、HTML、CSSの文字セットとエンコーディング
  • HTTP文字セットパラメータの設定

HTTPヘッダーとHTMLメタタグ(またはXHTMLがXMLとして機能する場合はXML宣言)の両方を使用することをお勧めします。

66
chroder 2008-11-11 11:30.

default_charsetphp.iniでの設定に加えてheader()、出力の前に、コード内からを使用して正しい文字セットを送信できます。

header('Content-Type: text/html; charset=utf-8');

PHPでのUnicodeの操作は、ほとんどの文字列関数がUnicodeで機能せず文字列を完全にマングルする可能性があることを理解している限り、簡単です。PHPは、「文字」を1バイト長と見なします。これで問題ない場合もあります(たとえば、explode()バイトシーケンスのみを検索し、それを区切り文字として使用するため、実際に検索する文字は関係ありません)。ただし、関数が実際に文字で機能するように設計されている場合、PHPは、テキストにUnicodeで検出されるマルチバイト文字が含まれていることを認識しません。

チェックインするのに適したライブラリはphputf8です。これにより、すべての「不良」関数が書き換えられるため、UTF8文字列で安全に作業できます。mbstring拡張機能のように、これを実行しようとする拡張機能もありますが、移植性が高いため、ライブラリを使用することをお勧めします(ただし、マスマーケット製品を作成しているので、それは私にとって重要です)。しかし、phputf8は、とにかく、パフォーマンスを向上させるために舞台裏でmbstringを使用できます。

37
Jim W. 2012-09-12 05:40.

PDOを使用している人に問題が見つかりました。その答えは、PDO接続文字列にこれを使用することでした。

$pdo = new PDO(
    'mysql:host=mysql.example.com;dbname=example_db',
    "username",
    "password",
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

これを取得したサイトはダウンしていますが、幸運にもGoogleキャッシュを使用して取得できました。

25
JDelage 2012-02-24 12:20.

私の場合、mb_split正規表現を使用するを使用していました。したがって、正規表現のエンコーディングがutf-8であることを手動で確認する必要もありました。mb_regex_encoding('UTF-8');

mb_internal_encoding()ちなみに、実行して内部エンコーディングがutf-8ではないことも発見し、を実行して変更しましたmb_internal_encoding("UTF-8");

23
Jimmy Kane 2014-01-27 23:16.

まず第一に、5.3PHP未満の場合は、いいえ。取り組むべき問題がたくさんあります。

ユニコード書記素文字列操作ローカリゼーションなどを適切にサポートするintlライブラリについて言及している人がいないことに驚いています。以下を参照してください。

PHPBenelux'14でのElizabethSmithの スライドによるPHPでのUnicodeサポートに関する情報を引用します。

INTL

良い:

  • ICUライブラリのラッパー
  • 標準化されたロケール、スクリプトごとにロケールを設定
  • 数値の書式設定
  • 通貨のフォーマット
  • メッセージのフォーマット(gettextを置き換えます)
  • カレンダー、日付、タイムゾーン、時間
  • 文字変換器
  • なりすましチェッカー
  • リソースバンドル
  • コンバーター
  • IDNサポート
  • 書記素
  • 照合
  • イテレータ

悪い:

  • zend_multibiteをサポートしていません
  • HTTP入出力変換をサポートしていません
  • 関数のオーバーロードをサポートしていません

mb_string

  • zend_multibyteサポートを有効にします
  • 透過的なHTTP入力/出力エンコーディングをサポート
  • strtoupperなどの機能性のためのいくつかのラッパーを提供します

ICONV

  • 文字セット変換のプライマリ
  • 出力バッファハンドラ
  • MIMEエンコーディング機能
  • 変換
  • 一部の文字列ヘルパー(len、substr、strpos、strrpos)
  • ストリームフィルター stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')

データベース

  • mysql:テーブルおよび接続(照合ではない)での文字セットと照合。また、mysqlを使用しないでください--msqliまたはPDO
  • postgresql:pg_set_client_encoding
  • sqlite(3):ユニコードとintlのサポートでコンパイルされていることを確認してください

他のいくつかの落とし穴

  • 3番目の部分の拡張子を使用しない限り、PHPおよびWindowsでUnicodeファイル名を使用することはできません。
  • exec、proc_open、およびその他のコマンドライン呼び出しを使用している場合は、すべてをASCIIで送信します
  • プレーンテキストはプレーンテキストではなく、ファイルにはエンコーディングがあります
  • iconvフィルターを使用してその場でファイルを変換できます

追加された機能が変更された場合などに備えて、この回答を更新します。

15
Puerto AGP 2014-09-10 17:39.

これらの驚くべき答えに追加する唯一のことは、ファイルをutf8エンコーディングで保存することを強調することです。ブラウザは、utf8をコードエンコーディングとして設定するよりも、このプロパティを受け入れることに気づきました。適切なテキストエディタであれば、これが表示されます。たとえば、Notepad ++にはファイルをエンコードするためのメニューオプションがあり、現在のエンコーディングが表示され、変更できます。私のすべてのphpファイルには、BOMなしでutf8を使用しています。

しばらく前に、誰かが設計したphp / mysqlアプリケーションのutf8サポートを追加するように頼まれましたが、すべてのファイルがANSIでエンコードされていることに気づいたので、ICONVを使用してすべてのファイルを変換し、データベーステーブルを変更してutf8 charsetとutf8_general_ciが照合し、接続後に「SET NAMES utf8」をデータベース抽象化レイヤーに追加し(5.3.6以前を使用している場合は、接続文字列でcharset = utf8を使用する必要があります)、phpマルチバイトを使用するように文字列関数を変更します同等の文字列関数。

14
Miguel Stevens 2014-01-13 23:37.

最近、を使用strtolower()すると、特殊文字の後にデータが切り捨てられる問題が発生する可能性があることを発見しました。

解決策は使用することでした

mb_strtolower($string, 'UTF-8');

mb_はMultiByteを使用します。より多くの文字をサポートしますが、一般的には少し遅くなります。

10
Abdul Sadik Yalcin 2015-05-06 11:36.

私はちょうど同じ問題を経験し、PHPマニュアルで良い解決策を見つけました。

すべてのファイルエンコーディングをUTF8に変更してから、接続のデフォルトエンコーディングに変更しました。これですべての問題が解決しました。

if (!$mysqli->set_charset("utf8")) { printf("Error loading character set utf8: %s\n", $mysqli->error);
} else {
   printf("Current character set: %s\n", $mysqli->character_set_name());
}

ソースを見る

9
JW. 2008-11-11 11:29.

PHPでは、マルチバイト関数を使用するか、mbstring.func_overloadをオンにする必要があります。そうすれば、複数のバイトを使用する文字がある場合、strlenのようなものが機能します。

また、応答の文字セットを識別する必要があります。上記のようにAddDefaultCharsetを使用するか、ヘッダーを返すPHPコードを記述できます。(または、HTMLドキュメントにMETAタグを追加することもできます。)

7
jalf 2008-11-11 11:48.

PHPでのUnicodeサポートは、依然として大きな混乱です。ISO8859文字列(内部で使用)をutf8に変換することはできますが、Unicode文字列をネイティブに処理する機能がありません。つまり、すべての文字列処理関数が文字列を壊して破損します。したがって、適切なutf8サポートのために別のライブラリを使用するか、すべての文字列処理関数を自分で書き直す必要があります。

簡単な部分は、HTTPヘッダーやデータベースなどで文字セットを指定することですが、PHPコードが有効なUTF8を出力しない場合は、それは問題ではありません。それは難しい部分であり、PHPは事実上何の助けにもなりません。(PHP6はこれの最悪の事態を修正することになっていると思いますが、それはまだしばらく先です)

7
Budimir Grom 2015-02-12 13:52.

クライアントとしてのPHPではなくMySQLサーバーに文字セットを決定させたい場合(古い動作;私の意見では好ましい)、、の下に追加skip-character-set-client-handshakeしてmy.cnf[mysqld]再起動してみてくださいmysql

これにより、UTF8以外を使用している場合に問題が発生する可能性があります。

6
commonpike 2011-01-15 06:13.

一番の答えは素晴らしいです。これが私が通常のdebian / php / mysqlセットアップでしなければならなかったことです:

// storage
// debian. apparently already utf-8

// retrieval
// the mysql database was stored in utf-8, 
// but apparently php was requesting iso. this worked: 
// ***notice "utf8", without dash, this is a mysql encoding***
mysql_set_charset('utf8');

// delivery
// php.ini did not have a default charset, 
// (it was commented out, shared host) and
// no http encoding was specified in the apache headers.
// this made apache send out a utf-8 header
// (and perhaps made php actually send out utf-8)
// ***notice "utf-8", with dash, this is a php encoding***
ini_set('default_charset','utf-8');

// submission
// this worked in all major browsers once apache
// was sending out the utf-8 header. i didnt add
// the accept-charset attribute.

// processing
// changed a few commands in php, like substr,
// to mb_substr

それがすべてでした!

2
castro_pereira 2019-03-25 09:27.

mysqlソリューションが必要な場合は、サーバーの移行後、2つのプロジェクトで同様の問題が発生しました。多くの解決策を検索して試した後、私はこれに出くわしました/これが機能する前に何もありません):

mysqli_set_charset($con,"utf8");

この行を設定ファイルに追加すると、すべて正常に機能します。

私はこの解決策を見つけました https://www.w3schools.com/PHP/func_mysqli_set_charset.asp HTMLクエリからの挿入を解決しようとしていたとき

がんばろう!

0
Accountant م 2019-08-24 09:10.

注:

ラテン文字以外の文字が?????????次のように表示されるという問題に直面しています。質問をしたところ、この正規の質問を参照して終了しました。何をしていても、すべてを試し??????????ましたMySQL

これは主に、間違った文字セットを使用してデータベースに挿入され、実際に疑問符文字に変換および保存された古いデータをテストしいるためです?。つまり、元のテキストを永久に失い、何をしようとしても取得でき???????ます。

この質問の回答から学んだことを新しいデータに再適用すると、問題を解決できる可能性があります。

0
Ijaz Ahmed Bhatti 2020-09-27 20:24.

connection.php内:mysqli_set_charset($ con、“ utf8”); SQL照合ではutf = 8

Related questions

MORE COOL STUFF

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire は、彼女が息子の Shelby Blackstock と共有する「楽しい」クリスマスの伝統を明らかにしました:「私たちはたくさん笑います」

Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルは、自然な髪のスタイリングをめぐってマライア・キャリーと結ばれました

メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子は家族との関係を修復できるという「希望を持っている」:「彼は父親と兄弟を愛している」

ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドは、パニックに陥った休暇の瞬間に、彼女がジャッド家の家長であることを認識しました

ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

スタートレックの50周年を称えるための最良の方法

スタートレックの50周年を称えるための最良の方法

来年は、スペースオペラの最も壮大で野心的なメディアシリーズの50周年を迎えます。しかし、スタートレックはその誇り高い遺産に沿って50歳の誕生日を迎えますか?スタートレックの誕生日を祝う方法はたくさんあります。

更新:合法的な大統領候補は数百万人を怒らせ、美しい女性は苦しむ

更新:合法的な大統領候補は数百万人を怒らせ、美しい女性は苦しむ

(画像提供:ゲッティイメージズ)ドナルド・トランプは、アメリカ合衆国大統領の立候補者となる比類のない外交的洞察力を示し、何百万人もの人々を怒らせ、彼の時代遅れの客体化に対する評価の主要な情報源を失いました。彼が立候補を発表し終える前にパレード。トランプ氏は演説の中で、この国で最も高い役職に選出された場合、米国との南の国境に壁を建設すると述べた一連の声明を発表した。

インターネット上で最も愚かな親ロシアのデマ

インターネット上で最も愚かな親ロシアのデマ

David L. Sternは、ウクライナのキエフを拠点とするフリーランスのライターです。

ディズニーフリークは今、独自の出会い系サイトを持っています

ディズニーフリークは今、独自の出会い系サイトを持っています

オンラインデートに関しては、船長、ベーコン愛好家、ポットヘッド向けに作られたサイトなど、長年にわたって選択できるニッチなサイトがたくさんあります。今、ディズニーファンは彼ら自身のマッチメイキングサイトを通して愛を見つけることができます。

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

米国のフィギュア スケートは、チーム イベントでの最終決定の欠如に「苛立ち」、公正な裁定を求める

ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

Amazonの買い物客は、わずか10ドルのシルクの枕カバーのおかげで、「甘やかされた赤ちゃんのように」眠れると言っています

何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

パデュー大学の教授が覚醒剤を扱った疑いで逮捕され、女性に性的好意を抱かせる

ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。

コンセプト ドリフト: AI にとって世界の変化は速すぎる

コンセプト ドリフト: AI にとって世界の変化は速すぎる

私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

犯罪擁護派のオークランドが暴力犯罪者のロミオ・ロレンゾ・パーハムを釈放

SF攻撃で91歳のアジア人女性が殴られ、コンクリートに叩きつけられた

認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。

ℝ

“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.

メリック・ガーランドはアメリカに失敗しましたか?

バイデン大統領の任期の半分以上です。メリック・ガーランドは何を待っていますか?

メリック・ガーランドはアメリカに失敗しましたか?

人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。

Language