ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Let's PHPコミュのDB INSERT時の文字化けについて

  • mixiチェック
  • このエントリーをはてなブックマークに追加
まだphpを使い始めて間もないので聞き苦しい質問でありましたら申し訳ありません。宜しくお願いします。

【開発環境】
fedora core 4
apache 2.0.54
php 4.4.1
mysql 4.0
文字コードはshift-jisです。
【MTA】
postfix2.2.2

現在携帯ユーザーから*****@****.****.jpというヴァーチャルドメインにメールを送信してもらい
***@***.jpというユーザーに引継ぎaliasを使って用意してあるphpプログラムを動かすという設定をしております。
ここまでは問題なく動作しておるのですが、そこから受け取ったtitleとbodyが文字化けして現在稼動
しているDBにinsertされてしまうという状態で悩んでおります。

headerやbodyの取得方法はMail_mimeDecodeを使用しております。

現在試してみたことはまず受け取ったメールheader,bodyの文字コードを確認(UTF-8)

INSERTする為に文字コードをUTF-8からShift-JISにmb_convert_encodingを使い変換を試みましたが
文字コードを変換できません。

補足ですが、現在稼動しているDBサーバーは通常INSERTする際文字化けは起きていません。
携帯からのメール本文とタイトルをINSERTする際にのみ化けてしまいます。
元々各キャリアの文字コードをそのまま引き継いでINSERTしようとしてるので起きる現象だと
思いますが…INSERT前に文字コードの変換ができません???
お分かりになる方にご教授願いたいと思い、こちらに書かせて
頂きました。宜しくお願い致します。

一部ソースを記述しておきます↓

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=Shift_JIS">
</head>
<?php

require_once('/usr/local/lib/php/Mail/mime.php');
require_once('/usr/local/lib/php/Mail/mimeDecode.php');

while(!feof(STDIN)) {
$source .= fread(STDIN, 4096);
}

$decoder = new Mail_mimeDecode( $source );

$parts = $decoder->getSendArray();

$params['include_bodies'] = true;
$params['decode_bodies'] = true;
$params['decode_headers'] = true;

$structure = $decoder->decode($params);

$to = $parts[0];
$body = $parts[2];
$from = $structure->headers['from'];
$subject = $structure->headers['subject'];

$chk_title = mb_detect_encoding($subject,"auto");
$chk_body = mb_detect_encoding($body,"auto");

print($chk_title); //ここでUTF-8
print($chk_body); //ここでUTF-8

$subject = mb_convert_encoding($subject,"SJIS","auto");
$body = mb_convert_encoding($body,"SJIS","auto");
//$subject = mb_convert_encoding($subject,"SJIS","UTF-8");
//$body = mb_convert_encoding($body,"SJIS","UTF-8");

$sql = "INSERT INTO **** SET ";
$sql .= "**** = '".$to."', ";
$sql .= "**** = '".$from."', ";
$sql .= "**** = '".$subject."'", ; //文字化け
$sql .= "**** = '".$body."'"; //文字化け

$*** = mysql_query($sql);


以上です。宜しくお願いします。

コメント(14)

> lllさん

下記の処理ですが・・・
$subject = mb_convert_encoding($subject,"SJIS","auto");
$body = mb_convert_encoding($body,"SJIS","auto");

第1引数を変えるとどうですか?
$subject = mb_convert_encoding($chk_title,"SJIS","auto");
$body = mb_convert_encoding($chk_body,"SJIS","auto");

あと、DBの文字コードは本当にShift-JISなのですか?
たぶん"auto"を渡してるからじゃないかな?UTF-8になるのは。
mb_detect_encoding関数は"auto"渡すとASCII、EUC、SJIS、UTF-8から値を返すんじゃなかったっけ?
あとphp.iniのmbstring設定もいろいろ関係してきたはず。
その辺はマニュアルやmb_detect_encoding/mb_convert_encodingを調べると詳しく出ていますよ。

>>ほーねっとさん
第1引数は変換する文字列だからエンコード結果をそこに入れてもあまり意味がないような
ほーねっと様返答ありがとうございます。

今サーバー管理者に問い合わせましたら文字コードがUTF−8ということでした。確認不足でした。もし今現状で文字コードを変えるとなると問題は出るのでしょうか?

ばーばら様返答ありがとうございます。
php.iniの設定ももう一度見直してみます。

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

携帯の文字コードはshift-jisだと認識していたのですが
今回のことで誤認識だったのかと思っていたところです。
んー
携帯から文字エンコードがUTF-8なメールが送信されるって聞いたことがないです
話の流れを見てると別の話と混在していませんか?

あと,文字エンコードはautoなど使わずとも基本的にメール内の情報で元文字エンコードを取得することができます.
しっかりそれで変換元の文字エンコードを指定することが文字化け対策の近道だと思います

#楽しようとして楽になってないの典型にみえる > mbstringのauto
mySQLの文字コードも

EUCにコンバートしてINSERT、でダメなら他の文字コードは?
mb_detect_encodingとかで出た結果がUTF-8だった・・・とかでしたらあまり信用できないかもしれませんね。
もしくは、受け取ったあとUTF-8にして取り回ししている仕様のはず・・・とか。

コンバート元が分からない時は、SQLなど取り扱ってる文字列を直接printしてみてIEとかがなんて判断するか見る方法なんてのがありますよ。
> 2: ばーばらさん

かなり恥ずかしい内容を書き込んでしまいました。^^;

で、メール内容がUTF-8なのは、
$params['decode_bodies'] = true;
$params['decode_headers'] = true;
で変換してるからではないでしょうか。

あと携帯の場合、絵文字や機種依存文字がある場合には、コード変換できないようです。

まずは、文字化けしている文字コードが何かを調べるところからはじめてはいかがでしょうか。
あと、DBに登録するなら、エスケープ処理も必要かと思います。
> で、メール内容がUTF-8なのは、
> $params['decode_bodies'] = true;
> $params['decode_headers'] = true;
> で変換してるからではないでしょうか。

MIMEデコードと文字エンコード変換は関係ない話ですよ
以前中のコードを見たことがありますが,文字エンコードの処理は入っていなかったと思います.

今簡単にMailパッケージ群を文字列を調べてみましたが,PHPで代表的な文字エンコード変換関数(iconv,mb_convert_encoding)は含まれていません.

$ pear list | grep -i Mail
Mail 1.1.9 stable
Mail_IMAP 1.1.0RC2 beta
Mail_IMAPv2 0.2.0 beta
Mail_Mbox 0.3.0 beta
Mail_Mime 1.3.1 stable
Mail_Queue 1.1.3 stable

$ grep -ri mb_convert_encoding /usr/share/php/pear/Mail*
$ grep -ri iconv /usr/share/php/pear/Mail*

一応mb_で始まるものも調べましたがIMAP拡張モジュールに関連するコードしか出てきません.
$ grep -ri mb_ /usr/share/php/pear/Mail*
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: * @param string $mb_name
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: * @param string $mb_rename
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: function manageMB($action, $mb_name, $mb_rename = NULL)
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: if (@imap_createmailbox($this->mailbox, imap_utf7_encode($this->mailboxInfo['host'].'INBOX.'.$mb_name))) {
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: $this->error->push(Mail_IMAPv2_ERROR, 'error', NULL, 'Unable to create MB: '.$mb_name);
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: if (empty($mb_rename)) {
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: if (@imap_renamemailbox($this->mailbox, $this->mailboxInfo['host'].'INBOX.'.$mb_name, $this->mailboxInfo['host'].'INBOX.'.$mb_rename)) {
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: $this->error->push(Mail_IMAPv2_ERROR, 'error', NULL, 'Unable to rename MB: '.$mb_name);
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: if (@imap_deletemailbox($this->mailbox, $this->mailboxInfo['host'].'INBOX.'.$mb_name)) {
/usr/share/php/pear/Mail/IMAPv2/ManageMB/ManageMB.php: $this->error->push(Mail_IMAPv2_ERROR, 'error', NULL, 'Unable to delete MB: '.$mb_name);
/usr/share/php/pear/Mail/IMAPv2/Debug/Debug.php: if (isset($_GET['dump_mb_info'])) {
/usr/share/php/pear/Mail/IMAPv2/Debug/Debug.php: if (isset($_GET['dump_mb_list'])) {
/usr/share/php/pear/Mail/IMAP.php: if (isset($_GET['dump_mb_list'])) {
/usr/share/php/pear/Mail/IMAP.php: if (isset($_GET['dump_mb_info'])) {
ちなみに常套手段としていくつかの場面でどんどんファイルにデータを保存するという手段があります.

・データ入手時(DBでSELECT,フォームから入力他)
・データ変換時(文字エンコード変換,バイナリASCII変換他)
・データ保存時(DBにINSERT他)

ファイルへの保存は通常余計な変換などは入らないので,後でテキストエディタで確認したり,バイナリエディタで確認したりできます.

#ふつーだと思うんだけどなーしないのかな
コメントくださった方々返答が遅くなり申し訳
ありません。

ELF 上鍵 様の言う通り、一度ファイルに書き出して
それを取得しinsertすることで文字化けを解消する
ことが出来ました。

返答くださった皆様ありがとうございました。
12: M.Maekawa さん>>
その通りです

11: lll さん>>
それで直るならどこかで不必要なロジックが入っていたのです
それがわからなければまた同じことがファイルに一度書き出すとかではダメなとき(パッと考えてもパフォーマンスに問題が出るでしょう)起こったら対処できないですよ.

#まぁ問題解決できない人々が多いので内外からは「だからPHPクオリティ」と呼ばれるわけですが(ゲラ
M.Maekawa 様

私も初めはデバックという形でファイルに書き出し
たのですが時間が押している事からファイルに
書き出した文字をもう一度取得するという事で文字化けを防げましたので解消という言葉とさせて頂いた次第です。
根本の原因は解決できていませんので今も原因は探っています。ただ現状正常に動いているので解消という言葉を使わせて頂いたのですが、妥当ではありませんでした。申し訳ありません。

ELF 上鍵 様
まだまだ知識が浅いので今回の指摘を元に更に精進していこうと思っております。色々とありがとうございました。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Let's PHP 更新情報

Let's PHPのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング