Posted by & filed under FuelPHP, PHP, Tech.

an evolution of signs
an evolution of signs / jm3

 

あるページから別のページへ飛ばすリダイレクト処理を書く場合、php で用意されている header 関数を利用できますが、FuelPHP でも同様のメソッドが用意されています。

Response::redirect

通常(?)のリダイレクト方法である Location を使う場合は問題ないのですが、Refresh を指定した場合、IEのみ “Internet Explorer ではこのページは表示できません” エラーが発生し、処理が中断してしまいました。

なんぞ?!ってなもんですが、 core を覗いてみたらそもそものお話だったので、その流れと自分が取った対応を記事にします。

なお、環境は以下の通りです。

  • CentOS 5.6
  • apache 2.2.3
  • FuelPHP 1.3
  • IE 8
ads

まずは 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 関数を使用したときの挙動をアクセスログで確認しました。なお、確認方法は

  1. Location ヘッダ送信
  2. Refresh ヘッダ送信
  3. ステータスコードを送信してから 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 を指定する場合の引数は、

  1. リダイレクト先 URL
  2. Refresh の文字列
  3. ステータスコード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 ユーザガイド 日本語版


Related Posts Plugin for WordPress, Blogger...

Leave a Reply

  • (will not be published)