an evolution of signs / jm3
あるページから別のページへ飛ばすリダイレクト処理を書く場合、php で用意されている header 関数を利用できますが、FuelPHP でも同様のメソッドが用意されています。
通常(?)のリダイレクト方法である Location を使う場合は問題ないのですが、Refresh を指定した場合、IEのみ “Internet Explorer ではこのページは表示できません” エラーが発生し、処理が中断してしまいました。
なんぞ?!ってなもんですが、 core を覗いてみたらそもそものお話だったので、その流れと自分が取った対応を記事にします。
なお、環境は以下の通りです。
- CentOS 5.6
- apache 2.2.3
- FuelPHP 1.3
- IE 8
まずは FuelPHP のドキュメントを確認
ドキュメント内、 Response クラスのにある redirect の説明部分、Parameters に以下様に説明があります。
$method ‘location’ Redirection method to use. Supported are ‘location’ and ‘refresh’.
Response – Classes – FuelPHP Documentation
つまり、’Location’ と ‘Refresh’ をサポートしてますよって事。ドキュメントのサンプルにもしっかりと
1 2 | // use a URL Response::redirect('http://example.com/home', 'refresh'); |
とありますね。というわけでそのまま使ってしまったのが事の始まりでした。
Chrome と Firefox だと動くけど IE だとエラー画面出るよ!
Chrome や Firefox でリダイレクト部分をブラウザ確認するとページのリダイレクトは行われていましたが、 IE で確認したところ “Internet Explorer ではこのページは表示できません” と言われる始末。おやおや、 core ソースを覗いてみましょう。
ここでキモとなるのが Response クラスのの238行目 – send_headers メソッド。このメソッドは redirect メソッド内で呼び出されます – 、ステータスコードを送信しています。$this->status の中にステータスコードが入っています。
fuel/core/classes/response.php
237 238 | $protocol = \Input::server('SERVER_PROTOCOL') ? \Input::server('SERVER_PROTOCOL') : 'HTTP/1.1'; header($protocol.' '.$this->status.' '.static::$statuses[$this->status]); |
ここではプログラム側で
Response::redirect('http://example.com/home', 'refresh'); |
と、第2引数までを指定しているのでステータスコードは指定していません。redirect メソッド第3引数で指定出来るステータスコードのデフォルト値は302です。となると、ここは302が指定されます。
どうやらここで失敗しているようです。
そもそも Refresh のときってステータスコードなんだ?
つまづいたときは基本に立ち返る。という事で素の PHP で header 関数を使用したときの挙動をアクセスログで確認しました。なお、確認方法は
- Location ヘッダ送信
- Refresh ヘッダ送信
- ステータスコードを送信してから Refresh ヘッダ送信
です。
なお、便宜上 URL を example.com としていますが、もし実験される場合は適宜 URL は変えてくださいまし。
1. Location ヘッダ送信
1 2 | <?php header("Location: http://example.com/redirected.php"); |
Chrome,Firefox,IE ともにページリダイレクト。ステータスコードは302。予想通りです。
2. Refresh ヘッダ送信
1 2 | <?php header("Refresh:0;url=http://example.com/redirected.php"); |
Chrome,Firefox,IE ともにページリダイレクト。ステータスコードは200。Refresh ヘッダのステータスコードは200でした。
3. ステータスコードを送信してから Refresh ヘッダ送信
ここでは、
- ステータスコード200を送信してから Refresh ヘッダを送信
- ステータスコード200以外を送信してから Refresh ヘッダを送信
の2ケース試してみました。
200指定
1 2 3 | <?php header("HTTP/1.1 200 OK"); header("Refresh:0;url=http://example.com/redirected.php"); |
Chrome,Firefox,IE ともにページリダイレクト。ステータスコードは200。
200以外を指定
1 2 3 | <?php header("301 Moved Permanently"); header("Refresh:0;url=http://example.com/redirected.php"); |
Chrome,Firefox はページリダイレクト。IE では “Internet Explorer ではこのページは表示できません” が発生。ステータスコードはすべて301。
という結果となりました。なるほど!IE のみ Refresh ヘッダがステータスコード200以外で飛んでくるとエラーとなるわけでござっした。
まとめ
FuelPHP の Response::redirect メソッドで Refresh を指定する場合の引数は、
- リダイレクト先 URL
- Refresh の文字列
- ステータスコード200
を指定してあげるのが正解のようです。
Response::redirect('http://example.com/home', 'refresh', 200); |
あとがき
そもそも Refresh を使った事がなかったのでステータスコードまで気が回っていませんでした。とほほ。
そういえば同じようなメソッドの使い方が出来る CodeIgniter だと、Refresh を指定した場合とくに気にすることなく200で飛んでたんだよな..とほほ。
オプションの第2引数で “location” (デフォルト) を使う方法か “refresh” を使う方法かを選べます。Location は高速ですが、Windows サーバでは時々問題を起こします。オプションの第3引数では送りたい HTTP Response Code を指定することができます。 たとえば検索エンジンが起こした301リダイレクトを送ることができます。デフォルトの Response Code は302です。第3引数は “location” だけで使え、”refresh” では使えません
URL ヘルパー : CodeIgniter ユーザガイド 日本語版
