- 締切済み
PHPからデータベースへの登録について
はじめまして。現在、仕事の関係でPHPのプログラムを勉強している者です。 早速ですが、質問させていただきます。 PHPで作成したフォームメールから別で用意したデータベースに 入力データを登録しようとしているのですが、エラーでうまく動作しません。 PHP側のコードミスもあるかもしれませんが、PHPを動作させているサーバーと データベースサーバーの文字コードが違う点も原因しているのでは?と調べている状況です。 フォームからのデータを送るPHP ⇒ Shift_jis PHPをアップしているWebサーバー ⇒ Shift_jis データベースサーバー ⇒ EUC-JP データベースへの接続は問題なく行えているようですので、 登録処理するコードの部分のみを書きます。(↓) ******************************************************************************** // データベースへの登録 $sql = "INSERT INTO FORM_DATA(DataNumber, Time, Name, Email, Area, Sex, Interest, Commnet, OS, IP) VALUES('$tsvcount', '$ymdhis', '$sender_name', '$mail_address', '$mail_area', '$mail_sex', '$mail_interest', '$mail_body', '$os', '$ip')"; $sql = mb_convert_encoding($sql, 'EUC-JP', 'sjis'); mysql_query("SET NAMES 'EUC-JP'"); $db_result = mysql_query($sql); print $sql; print $db_result; if (!$db_result) { exit('Error! データを登録できませんでした。'); } // データベースとの接続解除 $db = mysql_close($db); if (!$db) { exit('データベースとの接続を閉じれませんでした。'); } **************************************************************************** PHP&Webサーバーとデータベースの文字コードを統一すればいい話かもしれませんが、 事情により異なる文字コードの環境で開発しております。 上記の通り、データベースに送信するSQL文はmb_convert_encoding()で「EUC-JP」に変換し、 mysql_query($sql);でデータベースに送信している形です。 この状態で送信すると、エラーとなり送ったSQL文を処理してくれません。 文字コードの変換処理、コードの記述など何が原因なのか分からず困っています。 考えられる原因と、解決策があればご教授いただきたいです。 ちなみに私はPHPはもちろんプログラム自体もまだ経験が浅く、 基礎的なことも理解していないことがかなりあります。 その上でご説明いただけますと大変有難いです。 ではよろしくお願い致します。
- みんなの回答 (5)
- 専門家の回答
みんなの回答
- shimix
- ベストアンサー率54% (865/1590)
マニュアルは読まれていないのでしょうか・・・ http://jp2.php.net/manual/ja/function.mysql-set-charset.php phpが5.2.3以降、MySQLが5.0.7以降なら、mysql_set_charsetでいいです。 php5.3.6以降ではないので、PDOを使うときに「DSNにcharsetを含められない」のはツライですが、何を使って書き直すかはまだわかりませんしね。
- shimix
- ベストアンサー率54% (865/1590)
大事なことなので >MySQLのバージョンは4以降だと思います。 MySQLは4.0と4.1ではまったくの別物です(4.1が出たときに文字セットの取り扱いで大混乱しました)。 ∴ 「4以降」というだけでは適切な手法が提示出来ません。
お礼
度々ありがとうございます。 調べたところ、バージョンは4ではなく「5.1.36」でした。 この場合、文字コードの取扱いが今の手法とかなり違うというでしょうか? お忙しいところ何度も申し訳ありません! 出来ればお教え頂けますと助かります。
- shimix
- ベストアンサー率54% (865/1590)
ANo.2です >変数については囲みはなしで認識しておりました。 MySQLiやPDOのプリペアドステートメントであれば(サーバ側から得た列情報を元に適切に処理してくれるので)自前であれこれする必要はありませんが、スクリプト側で全部組み立てるときには、varcharやtextなどの「文字列」は引用符で括る必要があります。でないと「カンマを含む文字列」なんて使えませんよね(引用符はmysql_real_escape_stringでエスケープされます)。 RTFM. http://jp.php.net/manual/ja/function.mysql-real-escape-string.php #まぁ本来はプリペアドステートメント(を使える手法)にするべきです >あと、「mysql_set_charset('sjis'); 」で”sjis”を指定してありますが、 >MySQLサーバは「EUC」になっており、送信時には「EUC」に変換する必要があると思ってました。 >この場合、sjisで指定するだけで問題ないのでしょうか? サーバ側ではMySQLの文字セットがEUC-JPなのは既知ですが、「どの文字セットのデータが送られてくるのか」はクライアントから通知しないとわかりませんよね。なので「今からSJISでデータを送るよ」というのを通知します。それによって受け取ったサーバがSJIS→EUC-JPを行います(読み取りのときは逆にEUC-JP→SJISして返される)。 http://dev.mysql.com/doc/refman/5.1/ja/charset-connection.html 全部自前でmb_convert_encodingするのであればmysql_set_charset('UJIS')と書けば「そのまま」ですが、MySQLサーバがやってくれることを自前でやる必要はありません。 蛇足ですが、PDOでは(php5.3.6以降)接続時のDSNでcharsetを指定します。 $dbh = new PDO('mysql:host=localhost;dbname=test;charset=sjis', 'username', 'password');
お礼
再度のご回答ありがとうございます。 丁寧に説明いただき大変助かります。 頂きました内容を参考に修正してみます。 ちなみに、こちらのPHPのバージョンは「5.2.6」でした。 MySQLのバージョンは4以降だと思います。 よろしくお願い致します。
- shimix
- ベストアンサー率54% (865/1590)
phpとMySQLのバージョンは各々いくつでしょうか? >mysql_query("SET NAMES 'EUC-JP'"); MySQLに送るのであれば UJIS ではありませんか?EUC-JPという文字セット名は存在しなかったような・・・ それ以前に(set namesでなく)mysql_set_charset関数を使うべきですし、mysql_set_charsetで(phpスクリプトのとおりの)SJISを指定すれば、mb_convert_encodingも不要です(MySQL4.1以降、クライアントサーバ間の文字セット変換が組み込まれています)。SQL文の組み立て時にmysql_readl_escape_stringを使うべきですが(POSTされたデータをエスケープせずにSQL文に入れるのは「やってはいけないこと」です)その場合にも、適切なクライアント側の文字セットが設定されていることが大前提です。 mysql_set_charset('sjis'); $sql = sprintf("INSERT INTO FORM_DATA(DataNumber, Time, Name, Email, Area, Sex, Interest, Commnet, OS, IP) VALUES('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", mysql_real_escape_string($tsvcount), mysql_real_escape_string($ymdhis), mysql_real_escape_string($sender_name), mysql_real_escape_string($mail_address), mysql_real_escape_string($mail_area), mysql_real_escape_string($mail_sex), mysql_real_escape_string($mail_interest), mysql_real_escape_string($mail_body), mysql_real_escape_string($os), mysql_real_escape_string($ip)); $db_result = mysql_query($sql); (重要) そもそもネイティブなMySQL関数自体が非推奨になっています。可能であれば、MySQLiもしくはPDOで書き直してプリペアドステートメントを使ってください。
お礼
早速のご回答ありがとうございます。 エスケープする点は全く頭にありませんでした。 記述いただきましたコードを参考に修正してみます。 頂いたコードについて1点質問です。 下記では変数を指定していますが、 各要素はシングルコーテーションで囲むものなのでしょうか? VALUES('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')", 変数については囲みはなしで認識しておりました。 あと、「mysql_set_charset('sjis'); 」で”sjis”を指定してありますが、 MySQLサーバは「EUC」になっており、送信時には「EUC」に変換する必要があると思ってました。 この場合、sjisで指定するだけで問題ないのでしょうか? 素人的な質問ばかりで誠に申し訳ありません。 もしお手数でなければ再度ご教授いただけますと助かります。
- __vicky__
- ベストアンサー率66% (2/3)
断定はできないけど ('$tsvcount', '$ymdhis', '$sender_name', '$mail_address', '$mail_area', '$mail_sex', '$mail_interest', '$mail_body', '$os', '$ip') の部分。 変数はシングルクオーテーションで囲むと展開できないんです。 これを ($tsvcount, $ymdhis, $sender_name, $mail_address, $mail_area, $mail_sex, $mail_interest, $mail_body, $os, $ip) としてやるとか {$tsycount}などと中括弧で囲むのもありです。 あと (DataNumber, Time, Name, Email, Area, Sex, Interest, Commnet, OS, IP) の部分を (`DataNumber`, `Time`, `Name`, `Email`, `Area`, `Sex`, `Interest`, `Commnet`, `OS`, `IP`) と【バックティック】という文字で囲ってやるとか・・。 とりあえず改善の余地があるところを言って見ました。
お礼
早速のご回答ありがとうございます。 ご指摘の点は修正してみましたが、エラーの解消には至りませんでした。 しかし大変勉強になりました!引き続き自分でも調べてみます。 この他、もし何かお気づきの点があればご指摘いただけますと助かります。 ありがとうございました!
お礼
お礼が遅くなり申し訳ありません。 お忙しいところ何度もありがとうございます。 あれからまたいろいろな人にアドバイスいただき、 何とか登録できるようになりました。 ありがとうございました! <(_ _)>