私は新しいサーバーをセットアップしていて、私のWebアプリケーションで完全にUTF-8をサポートしたいです。私は過去にこれを既存のサーバーで試したことがあり、常にISO-8859-1にフォールバックしなければならなくなったようです。
エンコーディング/文字セットを正確にどこに設定する必要がありますか?これを行うには、Apache、MySQL、およびPHPを設定する必要があることを認識しています - 従うことができる標準的なチェックリストはありますか。
これは、MySQL 5、PHP、5、およびApache 2を実行する新しいLinuxサーバー用です。
データストレージ:
データベース内のすべてのテーブルとテキスト列でutf8mb4
文字セットを指定します。これにより、MySQLはUTF-8でネイティブにエンコードされた値を物理的に保存および取得します。 utf8mb4
照合が指定されている場合、MySQLは暗黙的にutf8mb4_*
エンコードを使用します(明示的な文字セットなし)。
MySQLの古いバージョン(<5.5.3)では、残念ながらUnicode文字のサブセットのみをサポートするutf8
を使用する必要があります。冗談だったらいいのに。
データアクセス:
アプリケーションコード(PHPなど)で、使用するDBアクセス方法に関係なく、接続文字セットをutf8mb4
に設定する必要があります。このように、MySQLはデータをアプリケーションに渡すとき、またはその逆の場合、ネイティブUTF-8からの変換を行いません。
一部のドライバは、接続文字セットを構成する独自のメカニズムを提供します。これは、独自の内部状態を更新し、接続で使用されるエンコーディングをMySQLに通知します。これは通常、推奨される方法です。 PHPの場合:
PHP≥5.3.6で PDO 抽象化レイヤーを使用している場合、 DSN でcharset
を指定できます。
$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ヘッダーを発行できます。これは、より多くの作業ですが、同じ効果があります。
json_encode()
を使用して出力をエンコードする場合、2番目のパラメーターとしてJSON_UNESCAPED_UNICODE
を追加します。
入力:
残念ながら、受信したすべての文字列を有効なUTF-8であるかどうかを確認してから、保存またはどこかで使用してください。 PHPの mb_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で安全なnotです通常のPHP文字列操作(連結など)で安全に実行できますが、ほとんどの場合、同等のmbstring
関数を使用する必要があります。
あなたが何をしているのかを知るために(読みましょう:それを台無しにしないで)、あなたは本当にUTF-8とそれが可能な限り低いレベルでどのように機能するかを知る必要があります。 tf8.com のリンクのいずれかをチェックして、知っておく必要のあるすべてを学ぶための優れたリソースを探してください。
chazomaticusの優れた答え :に1つ追加したいと思います。
METAタグも忘れないでください(このように、または HTML4またはXHTML版の )。
<meta charset="utf-8">
それは些細なように思えますが、IE7は私にそれ以前に問題を与えました。
私はすべてを正しくやっていました。データベース、データベース接続、およびContent-Type HTTPヘッダーはすべてUTF-8に設定されており、他のすべてのブラウザでは問題なく動作していましたが、Internet Explorerは依然として「西ヨーロッパ」エンコーディングの使用を主張しました。
ページにMETAタグがないことがわかりました。それを追加して問題を解決しました。
編集:
W3Cは実際にはI18N専用のかなり大きな セクションを持っています 。この問題に関連した記事がいくつかあります。HTTP、(X)HTML、およびCSSに関するものです。
彼らは、HTTPヘッダとHTMLメタタグ(またはXHTMLがXMLとして機能する場合はXML宣言)の両方を使用することを推奨します。
Php.iniでdefault_charset
を設定することに加えて、コードの中からheader()
を使って正しい文字セットを送ることができます。
header('Content-Type: text/html; charset=utf-8');
PHPでのUnicodeの使用は、ほとんどの 文字列関数がUnicodeで機能しないことを理解している限り簡単です。一部の文字列は完全に に変換されることがあります。 PHPは、「文字」を1バイト長と見なします。時にはこれで問題ありません(例えば、explode()
はバイトシーケンスだけを探してそれを区切り文字として使います - だから実際にどんな文字を探すかは関係ありません)。しかし、その関数が実際にcharactersで動作するように設計されている場合、PHPはあなたのテキストがUnicodeで見つかるマルチバイト文字を持っているとは思わない。
チェックインするのに良いライブラリは phputf8 です。これはすべての「悪い」関数を書き換えるので、UTF-8文字列を安全に扱うことができます。 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"));
私がこれを取ったサイトはダウンしていて、幸いにもグーグルキャッシュを使ってそれを得ることができました。
私の場合は、regexを使っているmb_split
を使っていました。そのため、mb_regex_encoding('UTF-8');
を実行して、正規表現のエンコードがutf-8であることを手動で確認する必要もありました。
ちなみに、私はmb_internal_encoding()
を実行して内部エンコーディングがutf-8ではないことを発見し、それをmb_internal_encoding("UTF-8");
を実行して変更しました。
あなたが5.3PHP未満であれば、まず第一にいいえ。あなたは取り組むべきたくさんの問題を抱えています。
intl ライブラリ、unicode、graphemes、文字列操作、localizationをサポートしているライブラリについては、誰も言及していません。そしてもっとたくさん、下記参照。
PHPでのUnicodeサポートについての情報をElizabeth Smithのスライド at PHPBenelux'14で引用します。
良い:
悪い:
stream_filter_append($fp, 'convert.iconv.ISO-2022-JP/EUC-JP')
機能が変更された場合などに備えて、この回答を更新します。
私は最近、strtolower()
を使用すると、データが特殊文字の後で切り捨てられる問題を引き起こす可能性があることを発見しました。
解決策は
mb_strtolower($string, 'UTF-8');
mb_はMultiByteを使います。より多くの文字をサポートしますが、一般的には少し遅くなります。
私がこれらの驚くべき答えに加える唯一のことはutf8エンコーディングであなたのファイルを保存することを強調することです、私はブラウザがあなたのコードエンコーディングとしてutf8を設定するよりこの特性を受け入れることに気づきました。たとえば、Notepad ++にはファイルエンコーディング用のメニューオプションがあり、現在のエンコーディングを表示して変更することができます。私のすべてのphpファイルには、BOMなしでutf8を使用します。
誰かが他の人によって設計されたphp/mysqlアプリケーションのためのutf8サポートを追加するよう私に頼んでもらった、私はすべてのファイルがANSIでエンコードされていることに気付いた。 utf8 charsetとutf8_general_ciを照合し、接続後にデータベース抽象化レイヤに 'SET NAMES utf8'を追加し(5.3.6以前を使用している場合は接続文字列でcharset = utf8を使用する必要があります)、phpマルチバイトを使用する文字列関数を変更します。文字列関数は同等です。
私はちょうど同じ問題を経験して、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のようなものはあなたが1バイト以上かかる文字を持っているならうまくいくでしょう。
また、あなたの回答の文字セットを特定する必要があります。上記のようにAddDefaultCharsetを使用するか、ヘッダーを返すPHPコードを記述することができます。 (または、あなたのHTML文書にMETAタグを追加することもできます。)
PHPでのUnicodeサポートは、まだ非常に混乱しています。 ISO8859文字列(内部で使用されている)をutf8に変換することはできますが、Unicode文字列をネイティブに処理する機能がありません。つまり、すべての文字列処理関数で文字列が壊れて破損します。したがって、適切なutf8サポートのためには別のライブラリを使用するか、またはすべての文字列処理関数を自分で書き直す必要があります。
簡単なのは、HTTPヘッダーやデータベースなどで文字セットを指定することだけですが、PHPコードが有効なUTF8を出力しない場合でも、問題はありません。それが難しい部分です、そしてPHPはあなたに事実上助けを与えません。 (私は、PHP6がこの最悪の問題を解決するはずだと思いますが、それでもまだしばらく時間がかかります)
一番上の答えは素晴らしいです。これは私が通常の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サーバにクライアントとしてPHPではなく文字セットを決定させたい場合(古い動作、私の考えでは好ましい)、skip-character-set-client-handshake
の下のmy.cnf
に[mysqld]
を追加し、mysql
を再起動します。
UTF8以外のものを使用している場合、これは問題を引き起こす可能性があります。
mysqlソリューションが必要な場合は、サーバーの移行後、私の2つのプロジェクトでも同様の問題がありました。多くの解決策を探して試した後、私はこれがうまくいく前に、この1つに出会いました。
mysqli_set_charset($con,"utf8");
この行を私の設定ファイルに追加すると、すべてうまくいきます。
私はこの解決策を見つけた https://www.w3schools.com/PHP/func_mysqli_set_charset.asp 私はHTMLクエリからの挿入を解決しようとしていたとき
がんばろう!