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


掲示板を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関数は表示されないのです。

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

回答の条件
  • 1人20回まで
  • 登録:2009/01/18 21:48:09
  • 終了:2009/01/25 21:50:02

回答(5件)

id:pahoo No.1

pahoo回答回数5960ベストアンサー獲得回数6332009/01/18 22:38:30

ポイント20pt

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

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

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

1.

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

2.

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

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

と指定しています。

3.

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

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

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

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

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

2009/01/18 23:42:34
id:sphire No.2

sphire回答回数115ベストアンサー獲得回数122009/01/19 02:33:00

ポイント20pt

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

http://jp.php.net/mb_convert_encoding

第3引数 from_encoding

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

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

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

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

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

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

id:loveylayer

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

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

を、

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

に変更してみました。

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

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

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

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

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

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

2009/01/20 01:12:43
id:pahoo No.3

pahoo回答回数5960ベストアンサー獲得回数6332009/01/20 11:37:49

ポイント20pt

#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;
?>
id:loveylayer

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

mb_internal_encoding('SJIS');

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

2009/01/20 22:44:26
id:sphire No.4

sphire回答回数115ベストアンサー獲得回数122009/01/21 14:07:00

ポイント20pt

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); で文字コード変換。

がんばってください。

id:loveylayer

>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行を使った方法、これから試してみます。

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

2009/01/23 23:16:46
id:sphire No.5

sphire回答回数115ベストアンサー獲得回数122009/01/24 14:45:42

ポイント20pt

スクリプトは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」してください。

  • id:sphire
    情報不足であまり意味のない回答をしておりました;

    以下の情報が必要ですので、教えてください!

    ・処理しているスクリプトと同じディレクトリで phpinfo(); を実行した時の「mbstring」セクション後半にかかれた内容をお知らせください。
    「Directive」「Local Value」「Master Value」というヘッダのある表の中身です。
    なお、「Directive」「Local Value」の内容のみで結構です。

    ・処理しているスクリプト中で「ini_set()」とか「mb_*()」といった関数を使用していれば、列挙してください。
    前述のmbstring設定を上書きしている可能性があります。
  • id:loveylayer
    コメントありがとうございます。

    ・phpinfo(); を実行したときの結果について、さっそく調べてみました。
    以下のようになりました。それぞれ、上段がDirective、下段がLocal Valueになっています。


    Directive
    Local Value

    mbstring.detect_order
    no value

    mbstring.encoding_translation
    Off

    mbstring.func_overload
    0

    mbstring.http_input
    pass

    mbstring.http_output
    pass

    mbstring.internal_encoding
    UTF-8

    mbstring.language
    Japanese

    mbstring.strict_detection
    Off

    mbstring.substitute_character
    no value



    ・「ini_set()」とか「mb_*()」のような関数は、全く使用しておりません!
  • id:pahoo
    >loveylayerさん
    #3のスクリプトを実行した時に表示される16進数を知りたいのですが、お願いできますか?
  • id:loveylayer
    >pahooさん
    コメントありがとうございます!

    フォームタグを使ったデータの入力で、
    属性値がnameのほうに「ああ」、属性値がmessageのほうに「あああ」と入力しました。
    結果が以下です。

    82a082a0
    82a082a082a0
    e38182e38182
    e38182e38182e38182
  • id:pahoo
    >loveylayerさん
    実行結果をありがとうございました。
    mb_convert_encoding は正常に動作しているようですね。

    問題のスクリプトの文字コード指定を確認してください。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません