なぜか$_POSTデータや$_FILESが空っぽになるのはどうして?
たとえばPHPでフォームデータの送信・受信プログラムをちゃんと作っているにも関わらず、サーバーへのデータ送信($_GET,$_POST,$_FILESなど)がうまくいかないアナタ。 送信先のパスをかっこつけてませんか?
かっこつけたパスを action属性に指定しないこと
うまく送信できない人のフォームは action属性が/path/to/upload のようにスラッシュをつけないディレクトリ名を指定しています。 で、実際に受け取る先のプログラムは/path/to/upload/index.php だったりする。
なぜ失敗するのでしょうか?
実は裏でリダイレクトされてデータが空っぽになっている
たしかに、/path/to/upload のように、末端にスラッシュやファイル名を直接指定しなくてもWEBサーバーはうまく解釈して /path/to/upload/index.php に導いてくれます。
Apache でこの役割を担ってくれるのが「mod_dir」という標準モジュールなんですが、基本的なに以下のような動きをします。
~「mod_dir」の解説ページより~
なお http://servername/foo/dirname という URL へのリクエストがあった際に、dirname というディレクトリがあれば、「最後にスラッシュをつけた形」の URL へのリダイレクトを送出します。 ディレクトリへのアクセスはスラッシュで終わっている必要があり、 mod_dir は、http://servername/foo/dirname/ へのリダイレクトを送出することになります。
ちゃんと「リダイレクト」と書いてありますね。 実際にリダイレクトされているログを見てみると、301ステータスコード(Moved Permanently) が返されて、スラッシュが付加されたアドレスに再度アクセスしています。
[30/Mar/2012:16:57:15 +0900] "GET /path/to/upload HTTP/1.1" 301 346 "-"... [30/Mar/2012:16:57:15 +0900] "GET /path/to/upload/ HTTP/1.1" 200 - "-"...
このリダイレクトの時点で送信されたデータもアップロードされたデータも消えてしまうのです。 もちろん、対策はちゃんとスラッシュ「/」を付加してあげることです。
終端をスラッシュで終わらせると明示的に upload ディレクトリ内のindex.htmlやDirectoryIndex ディレクティブで指定したファイル名を探しだしてアクセスします。
DirectoryIndex に指定したファイルへのアクセスではリダイレクトは発生しないので、データが無事に送信されます。 もちろん、明示的に index.php などを指定してもOKですよ。
どうしてもかっこいいパスを付けたければ、mod_rewrite を使う
かっこいいパスがどうしても付けたいんだ!という人は、Apache内でURLの書き換えを行うことができる「mod_rewrite」を利用してみましょう。
たとえば、「/path/to/upload」を指定して、「/path/to/upload/index.php」にアクセスさせつつ、送信データも引き継がせたい場合はApacheの設定ファイルで以下のように指定しましょう。
DirectorySlash Off RewriteEngine On RewriteRule ^path/to/upload$ /path/to/upload/index.php [L,QSA]
DirectorySlashは終端に自動でスラッシュをつける機能をオフにします。 ディレクトリを指定して設定するか、.htaccessファイルで特定のディレクトリのみに指定しておかないと、思わぬ誤動作を起こしかねないので注意しましょうね。
QSAフラグは、フォームをGET形式で送信した場合に、クエリーがちゃんと置き換え先URLにも引き継がれるようにするための設定です。
2012-03-30