ご存知のように、codeigniterでは、フォームは_/class/function/ID
_のページです。ここで、classはコントローラー名、functionはコントローラー内のメソッド、IDはそのメソッドに渡すパラメーターです。
典型的な使用法は(たとえば、本のサイトの場合)、適切な本をデータベースに照会する関数に本のIDを渡すことです。私の問題はこれです:データベースに存在しないIDをいじり回して(URL文字列に)ランダムに入力しました(通常のポイントとクリックのブラウズではこれは起こりません)、残りのクエリが原因でデータベースエラーが発生します存在しないIDで実行しようとしています。
IDを使用する前に返された行があるかどうかを確認するコードを記述しましたが、IDが存在しない場合、ユーザーに空白ページなどではなく404エラーページを取得してもらいたいのです(これは適切な機能)。これは、検索エンジンで混乱しないように、真の404ページである必要があります(404ページのように見えるビューを単にロードするだけではありません)。さて-だから私の質問はこれです:通常のプログラムロジックフロー内で(上記のように)codeigniterを使用して404エラーを強制するにはどうすればよいですか?ありがとう。
pdate:コードイグナイターにはshow_404('page')
関数がありますが、これにより真のHTTP 404エラーが生成されるとは思いません...
show_404()
は、検索エンジンが404ページとして登録するための適切なヘッダーを実際に送信します(404ステータスを送信します)。
Firefoxアドオンを使用して、show_404()
を呼び出すときに受信したヘッダーを確認します。適切なHTTPステータスコードを送信することがわかります。
デフォルトを確認するapplication/errors/error_404.php
。最初の行は次のとおりです。
<?php header("HTTP/1.1 404 Not Found"); ?>
その行はHTTPステータスを404に設定します。検索エンジンがページを404ページとして読み取るために必要なのはこれだけです。
$this->output->set_status_header('404');
404ヘッダーを生成します。
カスタムエラーページが必要な場合は、次のことを実行できます。ライブラリでファイル名を作成しますMY_ExceptionsとCI_Exceptionsで拡張します。そしてshow_404()関数をオーバーライドしますこの関数では、&get_instance()関数を使用してControllerクラスのインスタンスを作成できます。このインスタンスを使用して、カスタム404エラーページをロードできます。
class MY_Exceptions extends CI_Exceptions {
public function __construct(){
parent::__construct();
}
function show_404($page = ''){ // error page logic
header("HTTP/1.1 404 Not Found");
$heading = "404 Page Not Found";
$message = "The page you requested was not found ";
$CI =& get_instance();
$CI->load->view('/*Name of you custom 404 error page.*/');
}
次の手順のみに従ってください:
ステップ1 application/config/routes.phpファイルを更新します
$route['404_override'] = 'error/error_404';
ステップ2コントローラフォルダexに独自のコントローラを作成します。 error.php
<?php
class Error extends CI_Controller
{
function error_404()
{
$data["heading"] = "404 Page Not Found";
$data["message"] = "The page you requested was not found ";
$this->load->view('error',$data);
}
}
?>
ステップビューフォルダexにビューを作成します。 error.php
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252" />
<title><?php echo $heading;?></title>
</head>
<body>
<?php echo $message;?>
</body>
</html>
これを使ってみてください
set_status_header(404);
はいshow_404()は404を送信しますが、地獄のように見えます。ここでいくつかのハックが提案されていますが、組み込みの機能を使用できるのになぜハックするのですか?
CI 2.0にアップグレード すると、すばらしい機能を使用できるようになります。
$route['404_override'] = 'errors/error_404';
そうすれば、CIインスタンスの早い段階でビュー、ライブラリ、ヘルパーをロードして適切に機能することを心配せずに、一般的なエラーコントローラーを使用できます。
私はあなたと同じ問題を抱えていて、CodeIgniter 3でこれに対する完全な解決策を見つけました。ここで、それを解決する方法を段階的に共有したいと思います。もちろん、SEO要件を満たすには、カスタム404ページをサポートする必要があります。
class ErrorController extends CI_Controller
{
public function __construct()
{
parent::__construct();
}
public function index()
{
$this->output->set_status_header('404');
return $this->load->view('errors/error_404');
}
}
<div>
<p>We are so sorry. The page you requested could not be found.</p>
</div>
$route['404_override'] = 'ErrorController';
$config['subclass_prefix'] = 'MY_';
class MY_Exceptions extends CI_Exceptions {
public function __construct() {
parent::__construct();
}
function show_404($page = '', $log_error = TRUE) {
$CI = &get_instance();
$CI->output->set_status_header('404');
$CI->load->view('errors/error_404');
echo $CI->output->get_output();
exit;
}
}
abstract class MY_Model extends CI_Model
{
protected $table = 'table_name';
public function __construct()
{
parent::__construct();
$this->load->database();
}
public function find($id)
{
$result = $this->db->get_where($this->table, ['id' => $id]);
$data = $result->row_object();
if (!$data) {
show_404();
}
return $data;
}
}
Application/controllersフォルダーにコントローラーを作成します。
class Error extends Controller
{
function error_404()
{
$this->load->view('error');
}
}
次に、application/libraryでapplication/libraries/MY_Router.phpを作成してルータークラスを拡張します。
class MY_Router extends CI_Router
{
private $error_controller = 'error';
private $error_method_404 = 'error_404';
function MY_Router()
{
parent::CI_Router();
}
// this is just the same method as in Router.php, with show_404() replaced by $this->error_404();
function _validate_request($segments)
{
// Does the requested controller exist in the root folder?
if(file_exists(APPPATH.'controllers/'.$segments[0].EXT))
{
return $segments;
}
// Is the controller in a sub-folder?
if(is_dir(APPPATH.'controllers/'.$segments[0]))
{
// Set the directory and remove it from the segment array
$this->set_directory($segments[0]);
$segments = array_slice($segments, 1);
if(count($segments) > 0)
{
// Does the requested controller exist in the sub-folder?
if(!file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].EXT))
{
return $this->error_404();
}
}
else
{
$this->set_class($this->default_controller);
$this->set_method('index');
// Does the default controller exist in the sub-folder?
if(!file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.EXT))
{
$this->directory = '';
return array();
}
}
return $segments;
}
// Can't find the requested controller...
return $this->error_404();
}
function error_404()
{
$segments = array();
$segments[] = $this->error_controller;
$segments[] = $this->error_method_404;
return $segments;
}
function fetch_class()
{
// if method doesn't exist in class, change
// class to error and method to error_404
$this->check_method();
return $this->class;
}
function check_method()
{
$class = $this->class;
if (class_exists($class))
{
if ($class == 'doc')
{
return;
}
if (! in_array('_remap', array_map('strtolower', get_class_methods($class)))
&& ! in_array(strtolower($this->method), array_map('strtolower', get_class_methods($class))))
{
$this->class = $this->error_controller;
$this->method = $this->error_method_404;
include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
}
}
}
}
ページが存在しない場合、エラーコントローラーにルーティングされます