質問: $_SERVER['REQUEST_URI']; echo $access_url; ``` $_SERVER['REQUEST_URI']を使用して取得した現在の閲覧ページのURLに 「一部の日本語」が含まれている場合に「文字化け」を起こしてしまいます。 そしてcronを使って15分毎にMYSQLにアクセスログの登録を行う際に 「文字化け」を起こしている箇所に来ると「エラー」が発生し、 データベースへの保存に失敗してしまいます。 該当箇所の文字化けです。 ``` /tag.php?tag=���D�������ԑg�����T�C�g&page=1 ``` 大部分の日本語の場合は問題なく ``` /tag.php?tag=%E7%BE%8E%E5%B0%91%E5%A5%B3%E5%A3%B0%E5%84%AA& ``` このような風に表示されるのですが 一部の日本語のみ文字化けを起こしてしまっていて困っています。 (必死に文字化けを起こす日本語を調べてみたのですが、発見する事も出来ませんでした。) 解決方法について ご存知の方や何かお気付きの点がありましたら お力をお貸し頂けると嬉しいです。 どうかよろしくお願いします。
回答: `$_SERVER`というPHPのスーパーグローバル変数はサーバーに来た生の情報が入っているので、マルチバイト文字は`urldecode()`でデコードしなければなりません。一方、特定のURLクエリ情報を連想配列で保持している`$_GET`は既にデコード済みの値が入っています。 DBに格納する場合は、URLエンコードされたままの文字列でも構いませんが、エスケープしなければならない文字列があるはずなので、PDOであれば`bindValue()`や`bindParam()`を使って格納します。 ``` //http://ドメイン名/tag.php?tag=%E7%BE%8E%E5%B0%91%E5%A5%B3%E5%A3%B0%E5%84%AA& $access_url = $_SERVER['REQUEST_URI']; //URLをデコードして表示 echo urldecode($access_url); //特定のURLクエリを表示(デコード済) echo $_GET['tag']; //DB格納の例 try { $db = new PDO('mysql:dbname=データベース名;host=ホスト名', 'ユーザー名', 'パスワード'); $stm = $db->prepare('INSERT INTO ... WHERE カラム名 = ? ...'); $stm->bindValue(1, $access_url, PDO::PARAM_STR); //文字列として格納 $stm->execute(); } catch (PDOException $e) { echo $e->getMessage(); } ``` 最近のメジャーなブラウザは、ロケーションバーのURLを自動的にURLをデコードします。 プログラムで処理する場合は、デコード前の文字コードと、デコード後の文字コードが同じでなければならないので注意してください。普通は`UTF-8`を一般的に使用します。Windows側の標準文字コードはWindows-31J(MS932)で、Shift-JISを拡張したものです。LinuxなどのOSは最近はUTF-8が標準です。