人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

文字エンコーディングに関する質問です。

掲示板をPHP×MYSQLで作成していますが、POSTメソッドで送られてきた文字列データを、PHPのmb_convert_encoding関数でUTF-8に変換すると、なぜか文字列そのものが消えてしまうという問題が起こっています。

簡単にコードを書くと、まずユーザーが投稿するページで、

<form method="post" action="?">
<input type="text" name="name">
<textarea name="message" rows="5" cols="60" wrap="on"></textarea>
<input type="submit" value="書込">
</form>

と書いています。次に、上記?のファイルで、

$name = $_POST['name'];
$message = $_POST['message'];
echo $name;
echo $message;
$name = mb_convert_encoding($name,"UTF-8");
$message = mb_convert_encoding($message,"UTF-8");
echo $name;
echo $message;

という処理を行っています。この処理は、MYSQLもPHPも文字コードをUTF-8にしているため、それに合わせるために行っています。
ここで、echo関数を4度使って、処理途中で文字列を確認するようになっていますが、最初の2度のechoはきちんと表示されるのに、後の2度のecho関数は表示されないのです。

この理由が分かる方はいらっしゃいませんでしょうか?

●質問者: loveylayer
●カテゴリ:インターネット ウェブ制作
✍キーワード:ECHO MESSAGE MySQL name PHP
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● pahoo
●20ポイント

以下の点をご確認ください。

  1. ご利用のPHPのバージョンは何ですか?
  2. ユーザーが投稿するページの文字コードは何ですか?
  3. POSTで送られてきた文字の中に、UTF-8に変換できない文字種(ローマ数字、○付数字、携帯絵文字、外字などの機種依存文字等)が含まれていませんか?
◎質問者からの返答

返信ありがとうございます!

1.

PHPのバージョンは5.1.6になります。

2.

ユーザーが投稿するページの文字コードは、SHIFT-JISです。

<meta http-equiv="Content-Type" content="text/html; charset=shift-JIS">

と指定しています。

3.

POSTで送る文字は、通常の日本語で試しています。ローマ数字や絵文字などの変わった文字は使っていません。

なお、なぜか半角英数字だとうまくいきます。

投稿→データベースへ格納→データベースからデータを取って表示

という一連の流れが、すべて半角英数字だとできるんです。

ですので、日本語の文字コードでどこかがおかしいのでは・・と考えています。


2 ● sphire
●20ポイント

mb_convert_encoding(); の使い方に問題があります。

http://jp.php.net/mb_convert_encoding

第3引数 from_encoding

変換前の文字エンコーディング名を指定します。

これは、配列またはカンマ区切りの文字列とすることが可能です。

from_encodingを指定しなかった場合は、内部文字エンコーディングを使用します。

第3引数に "SJIS" を指定すれば解消するはずです。

なお、現状は UTF-8→UTF-8の変換をかけているだけなのですが

UTF-8に現れ得ないバイト列は削除されますので、SJISのマルチバイトが消えるのだと思います。

◎質問者からの返答

ご返答ありがとうございます。

$name = mb_convert_encoding($name,"UTF-8");

を、

$name = mb_convert_encoding($name,"UTF-8","SJIS");

に変更してみました。

・・・が、やっぱりうまくいきませんでした。

4つのechoのうち、この関数を通した後の2つは文字化けしたようになりました。

(これが良いのかどうかはわかりませんが・・)

それに、データベースに正しい文字が入らないですね。

日本語が「?」となってMYSQLに格納されてしまいます。

それをhtmlで表示しても、やはり「?」のままです。


3 ● pahoo
●20ポイント

#1で回答した者です。コメントをありがとうございました。

ということは、ご質問のPHPスクリプトも Shift_JIS(SJIS)で書いている、もしくはUTF-8であることを明示していないということですね。

となると、mb_convert_encoding 関数で正常に UTF-8 に変換されているものの、表示文字コードが異なるので echo で表示されていないのではないでしょうか。


ご質問の処理を、以下のコードにして、結果をご確認ください。

このスクリプトは、変換前と変換後の文字コードをASCII 16進数で表示するものです。mb_convert_encoding 関数が正常に作用しているかどうか確認します。


<?php
mb_internal_encoding('SJIS');
echo <<< EOF
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS" />
</head>
<body>

EOF;

$name = $_POST['name'];
$message = $_POST['message'];
echo bin2hex($name) . '<br />';
echo bin2hex($message) . '<br />';
$name = mb_convert_encoding($name, 'UTF-8', 'SJIS');
$message = mb_convert_encoding($message, 'UTF-8', 'SJIS');
echo bin2hex($name) . '<br />';
echo bin2hex($message) . '<br />';

echo <<< EOF
</body>
</html>

EOF;
?>
◎質問者からの返答

丁寧なご返答どうもありがとうございます!

mb_internal_encoding('SJIS');

を試してみましたが、やはりダメでした・・文字化けしたままです。


4 ● sphire
●20ポイント

phpinfo()ありがとうございます。

気になる点

・mbstring.detect_order → no value

明示的に指定すべき。なのですが、、

POSTする元のページはSJISてのは本当ですか?

同じサーバですか?だとすると mbstring.http_output → pass ですので

<meta http-equiv="Content-Type" content="text/html; charset=shift-JIS">

と書くだけではSJISで出力されないはず、

ということで、id:pahoo さんの言うとおり、スクリプトがSJISなのですかね。

この時点で文字化けを解消できる気がしないですけど…

望みの綱は .htaccess に

php_value mbstring.internal_encoding SJIS

php_value mbstring.script_encoding SJIS

と書いてみる。

----

一番いいのは、サーバーの設定に合わせて全てUTF-8に書き直すことです。

スクリプトの文字コードをUTF-8にする。

HTMLを出力する時には mb_http_output('SJIS'); する。

受け取った文字列は mb_convert_variables('UTF-8', 'SJIS', $var); で文字コード変換。

がんばってください。

◎質問者からの返答

>sphireさん

回答ありがとうございます。

すいません、ちょっと理解できない点が多いです。。

・サーバはさくらの専用サーバ1台しか使っていません。

・Apache、PHP、MySQLの文字コードの設定はUTF-8になっています。

・すべてのページのmetaタグに

<meta http-equiv="Content-Type" content="text/html; charset=shift-JIS">

を入れています。

・PHPでは特に文字コードの指定はしていません。

・"スクリプトがSJIS"というのは、

mb_internal_encoding('SJIS');

といった処理という意味でしょうか・・?


mb_http_output('SJIS');

mb_convert_variables('UTF-8', 'SJIS', $var);

の2行を使った方法、これから試してみます。

ご意見どうもありがとうございます!


5 ● sphire
●20ポイント

スクリプトはUTF-8

mbstring.encoding_translation=Off

mbstring.internal_encoding=UTF-8

mbstring.http_output=pass

ということは、出力されているHTMLはUTF-8のはず。なのに

<meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS">

なんて書いちゃいけません。そりゃブラウザも混乱します。

文字化けの原因はあなたが作っているのです。

スクリプトの先頭で

ini_set('mbstring.encoding_translation', true);

mb_http_output('SJIS');

を実行してください。これで正しくSJIS出力されるはず。

ここで初めて、metaタグでSJIS宣言してもOKだと思います。

次に、ブラウザは正しくSJISを送信してくるはずですので、文字コードを変換してあげます。

mb_convert_variables('UTF-8', 'SJIS', $var);

これでたぶん、UTF-8として扱うことができます。

なお、Apacheの設定で万一「AddDefaultCharset utf-8」などと書いてあると

HTTPヘッダに「Content-Type: text/html; charset=utf-8」とか吐きよるので、気を付けてください。

その場合は.htaccessで「AddDefaultCharset Off」してください。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ