新しいサーバーをセットアップしていて、WebアプリケーションでUTF-8を完全にサポートしたいと考えています。私は過去に既存のサーバーでこれを試しましたが、常にISO-8859-1にフォールバックする必要があるようです。
エンコーディング/文字セットを正確にどこに設定する必要がありますか?これを行うには、Apache、MySQL、およびPHPを構成する必要があることを認識しています。従うことができる標準のチェックリストがありますか、または不一致が発生する場所のトラブルシューティングを行うことができますか?
これは、MySQL 5、PHP、5、およびApache2を実行する新しいLinuxサーバー用です。
データストレージ:
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_charset
php.iniオプションを使用するかContent-Type
、自分でMIMEヘッダーを手動で発行できます。これは手間がかかりますが同じ効果があります。
を使用して出力をエンコードする場合は、2番目のパラメーターとしてjson_encode()
追加JSON_UNESCAPED_UNICODE
します。
入力:
残念ながら、受信したすべての文字列を保存したり、どこでも使用したりする前に、有効なUTF-8であることを確認する必要があります。PHPmb_check_encoding()
がそのトリックを実行しますが、それを忠実に使用する必要があります。悪意のあるクライアントは任意のエンコーディングでデータを送信できるため、これを回避する方法は実際にはありません。PHPにこれを確実に実行させるためのトリックは見つかりませんでした。
現在のHTML仕様を読んだところ、次のサブ箇条書きは不要であるか、最新のHTMLではもはや有効ではありません。私の理解では、ブラウザはドキュメントに指定された文字セットでデータを処理して送信します。ただし、古いバージョンのHTML(XHTML、HTML4など)をターゲットにしている場合は、次の点が役立つ場合があります。
accept-charset
すべての<form>
タグに属性を追加することです<form ... accept-charset="UTF-8">
。<form>
鬼ごっこ。その他のコードに関する考慮事項:
当然のことながら、提供するすべてのファイル(PHP、HTML、JavaScriptなど)は、有効なUTF-8でエンコードする必要があります。
UTF-8文字列を処理するたびに、安全に処理することを確認する必要があります。残念ながら、これは難しい部分です。PHPのmbstring
拡張機能を多用したいと思うかもしれません。
PHPの組み込み文字列操作は、デフォルトではUTF-8で安全ではありません。通常のPHP文字列操作(連結など)で安全に実行できることがいくつかありますが、ほとんどの場合、同等のmbstring
関数を使用する必要があります。
何をしているのかを知るには(読んでください:混乱させないでください)、UTF-8とそれが可能な限り低いレベルでどのように機能するかを本当に知る必要があります。あなたが知る必要があるすべてを学ぶためのいくつかの良いリソースについては、utf8.comからのリンクのいずれかをチェックしてください。
chazomaticusの優れた答えに1つ追加したいと思います:
METAタグも忘れないでください(このように、またはHTML4またはXHTMLバージョンのように):
<meta charset="utf-8">
それは些細なことのように思えますが、IE7は以前にそれに関する問題を私に与えました。
私はすべてを正しくやっていた。データベース、データベース接続、およびContent-Type HTTPヘッダーはすべてUTF-8に設定されており、他のすべてのブラウザーでも正常に機能しましたが、InternetExplorerは依然として「西ヨーロッパ」エンコーディングの使用を主張していました。
ページにMETAタグがないことが判明しました。それを追加することで問題は解決しました。
編集:
W3Cには、実際にはI18N専用のかなり大きなセクションがあります。この問題に関連する記事が多数あります。HTTP、(X)HTML、CSSの側面について説明しています。
HTTPヘッダーとHTMLメタタグ(またはXHTMLがXMLとして機能する場合はXML宣言)の両方を使用することをお勧めします。
default_charset
php.iniでの設定に加えてheader()
、出力の前に、コード内からを使用して正しい文字セットを送信できます。
header('Content-Type: text/html; charset=utf-8');
PHPでのUnicodeの操作は、ほとんどの文字列関数がUnicodeで機能せず、文字列を完全にマングルする可能性があることを理解している限り、簡単です。PHPは、「文字」を1バイト長と見なします。これで問題ない場合もあります(たとえば、explode()
バイトシーケンスのみを検索し、それを区切り文字として使用するため、実際に検索する文字は関係ありません)。ただし、関数が実際に文字で機能するように設計されている場合、PHPは、テキストにUnicodeで検出されるマルチバイト文字が含まれていることを認識しません。
チェックインするのに適したライブラリはphputf8です。これにより、すべての「不良」関数が書き換えられるため、UTF8文字列で安全に作業できます。mbstring拡張機能のように、これを実行しようとする拡張機能もありますが、移植性が高いため、ライブラリを使用することをお勧めします(ただし、マスマーケット製品を作成しているので、それは私にとって重要です)。しかし、phputf8は、とにかく、パフォーマンスを向上させるために舞台裏でmbstringを使用できます。
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キャッシュを使用して取得できました。
私の場合、mb_split
正規表現を使用するを使用していました。したがって、正規表現のエンコーディングがutf-8であることを手動で確認する必要もありました。mb_regex_encoding('UTF-8');
mb_internal_encoding()
ちなみに、実行して内部エンコーディングがutf-8ではないことも発見し、を実行して変更しましたmb_internal_encoding("UTF-8");
。
まず第一に、5.3PHP未満の場合は、いいえ。取り組むべき問題がたくさんあります。
ユニコード、書記素、文字列操作、ローカリゼーションなどを適切にサポートするintlライブラリについて言及している人がいないことに驚いています。以下を参照してください。
PHPBenelux'14でのElizabethSmithの スライドによるPHPでのUnicodeサポートに関する情報を引用します。
良い:
悪い:
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
追加された機能が変更された場合などに備えて、この回答を更新します。
これらの驚くべき答えに追加する唯一のことは、ファイルを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マルチバイトを使用するように文字列関数を変更します同等の文字列関数。
最近、を使用strtolower()
すると、特殊文字の後にデータが切り捨てられる問題が発生する可能性があることを発見しました。
解決策は使用することでした
mb_strtolower($string, 'UTF-8');
mb_はMultiByteを使用します。より多くの文字をサポートしますが、一般的には少し遅くなります。
私はちょうど同じ問題を経験し、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());
}
ソースを見る
PHPでは、マルチバイト関数を使用するか、mbstring.func_overloadをオンにする必要があります。そうすれば、複数のバイトを使用する文字がある場合、strlenのようなものが機能します。
また、応答の文字セットを識別する必要があります。上記のようにAddDefaultCharsetを使用するか、ヘッダーを返すPHPコードを記述できます。(または、HTMLドキュメントにMETAタグを追加することもできます。)
PHPでのUnicodeサポートは、依然として大きな混乱です。ISO8859文字列(内部で使用)をutf8に変換することはできますが、Unicode文字列をネイティブに処理する機能がありません。つまり、すべての文字列処理関数が文字列を壊して破損します。したがって、適切なutf8サポートのために別のライブラリを使用するか、すべての文字列処理関数を自分で書き直す必要があります。
簡単な部分は、HTTPヘッダーやデータベースなどで文字セットを指定することですが、PHPコードが有効なUTF8を出力しない場合は、それは問題ではありません。それは難しい部分であり、PHPは事実上何の助けにもなりません。(PHP6はこれの最悪の事態を修正することになっていると思いますが、それはまだしばらく先です)
クライアントとしてのPHPではなくMySQLサーバーに文字セットを決定させたい場合(古い動作;私の意見では好ましい)、、の下に追加skip-character-set-client-handshake
してmy.cnf
、[mysqld]
再起動してみてくださいmysql
。
これにより、UTF8以外を使用している場合に問題が発生する可能性があります。
一番の答えは素晴らしいです。これが私が通常の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
それがすべてでした!
mysqlソリューションが必要な場合は、サーバーの移行後、2つのプロジェクトで同様の問題が発生しました。多くの解決策を検索して試した後、私はこれに出くわしました/これが機能する前に何もありません):
mysqli_set_charset($con,"utf8");
この行を設定ファイルに追加すると、すべて正常に機能します。
私はこの解決策を見つけました https://www.w3schools.com/PHP/func_mysqli_set_charset.asp HTMLクエリからの挿入を解決しようとしていたとき
がんばろう!
注:
ラテン文字以外の文字が?????????
次のように表示されるという問題に直面しています。質問をしたところ、この正規の質問を参照して終了しました。何をしていても、すべてを試し??????????
ましたMySQL
。
これは主に、間違った文字セットを使用してデータベースに挿入され、実際に疑問符文字に変換および保存された古いデータをテストしているためです?
。つまり、元のテキストを永久に失い、何をしようとしても取得でき???????
ます。
この質問の回答から学んだことを新しいデータに再適用すると、問題を解決できる可能性があります。
connection.php内:mysqli_set_charset($ con、“ utf8”); SQL照合ではutf = 8
Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。
メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.
ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。
ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.
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?
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!
来年は、スペースオペラの最も壮大で野心的なメディアシリーズの50周年を迎えます。しかし、スタートレックはその誇り高い遺産に沿って50歳の誕生日を迎えますか?スタートレックの誕生日を祝う方法はたくさんあります。
(画像提供:ゲッティイメージズ)ドナルド・トランプは、アメリカ合衆国大統領の立候補者となる比類のない外交的洞察力を示し、何百万人もの人々を怒らせ、彼の時代遅れの客体化に対する評価の主要な情報源を失いました。彼が立候補を発表し終える前にパレード。トランプ氏は演説の中で、この国で最も高い役職に選出された場合、米国との南の国境に壁を建設すると述べた一連の声明を発表した。
オンラインデートに関しては、船長、ベーコン愛好家、ポットヘッド向けに作られたサイトなど、長年にわたって選択できるニッチなサイトがたくさんあります。今、ディズニーファンは彼ら自身のマッチメイキングサイトを通して愛を見つけることができます。
ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。
何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください
ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。
私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。
認知症を患っている 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.
人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。