CodeIgniter 路由和 404 自定义错误

Posted

技术标签:

【中文标题】CodeIgniter 路由和 404 自定义错误【英文标题】:CodeIgniter Routing and 404 Custom Errors 【发布时间】:2016-08-04 15:53:29 【问题描述】:

我使用 CodeIgniter。

我使用 routes.php 文件根据 url 的结构将某些 url 路由到不同的文件。一切正常。

然而,几个月前,我想我会添加一个自定义 404 页面。我做到了,一切似乎都很好。

但是,我刚刚意识到我网站上的每个页面(主页除外)都会给出 404 错误的服务器响应,但会向人类用户显示正确的页面作为自定义页面!

我不知道这是怎么回事,但这显然是一场噩梦,因为我现在没有从所有搜索引擎列表中编入索引!!!域名是http://citylightstours.com

ROUTES.PHP

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
| -------------------------------------------------------------------------
| URI ROUTING
| -------------------------------------------------------------------------
| This file lets you re-map URI requests to specific controller functions.
|
| Typically there is a one-to-one relationship between a URL string
| and its corresponding controller class/method. The segments in a
| URL normally follow this pattern:
|
|   example.com/class/method/id/
|
| In some instances, however, you may want to remap this relationship
| so that a different class/function is called than the one
| corresponding to the URL.
|
| Please see the user guide for complete details:
|
|   http://codeigniter.com/user_guide/general/routing.html
|
| -------------------------------------------------------------------------
| RESERVED ROUTES
| -------------------------------------------------------------------------
|
| There area two reserved routes:
|
|   $route['default_controller'] = 'welcome';
|
| This route indicates which controller class should be loaded if the
| URI contains no data. In the above example, the "welcome" class
| would be loaded.
|
|   $route['404_override'] = 'errors/page_missing';
|
| This route will tell the Router what URI segments to use if those provided
| in the URL cannot be matched to a valid route.
|
*/

$route['default_controller'] = "content";
$route['en/(:num)/(:any)'] = "content/en/$1";
$route['de/(:num)/(:any)'] = "content/de/$1";
$route['es/(:num)/(:any)'] = "content/es/$1";
$route['it/(:num)/(:any)'] = "content/it/$1";
$route['ar/(:num)/(:any)'] = "content/ar/$1";
$route['404_override'] = '';


/* End of file routes.php */
/* Location: ./application/config/routes.php */

.HTACCESS 文件:

<IfModule mod_rewrite.c>
# Development
    RewriteEngine On
    RewriteBase /
    RewriteCond %REQUEST_FILENAME !-f
    RewriteCond %REQUEST_FILENAME !-d
    RewriteCond $1 !^(index\.php|images|scripts|styles|vendor|robots\.txt)
    RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>

DirectoryIndex index.php
RewriteEngine on
RewriteCond $1 !^(index\.php|images|css|js|robots\.txt|favicon\.ico)
RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_FILENAME !-d
RewriteRule ^(.*)$ ./index.php/$1 [L,QSA]

# ----------------------------------------------------------------------
# Better website experience for IE users
# ----------------------------------------------------------------------

<IfModule mod_setenvif.c>
  <IfModule mod_headers.c>
    BrowserMatch MSIE ie
    Header set X-UA-Compatible "IE=Edge,chrome=1" env=ie
  </IfModule>
</IfModule>

<IfModule mod_headers.c>
  Header append Vary User-Agent
</IfModule>


# ----------------------------------------------------------------------
# Webfont access
# ----------------------------------------------------------------------

<FilesMatch "\.(ttf|otf|eot|woff|font.css)$">
  <IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
  </IfModule>
</FilesMatch>

# ----------------------------------------------------------------------
# Proper MIME type for all files
# ----------------------------------------------------------------------

# audio
AddType audio/ogg                      oga ogg

# video
AddType video/ogg                      .ogv
AddType video/mp4                      .mp4
AddType video/webm                     .webm

# Proper svg serving. Required for svg webfonts on iPad
#   twitter.com/FontSquirrel/status/14855840545
AddType     image/svg+xml              svg svgz 
AddEncoding gzip                       svgz

# webfonts                             
AddType application/vnd.ms-fontobject  eot
AddType font/truetype                  ttf
AddType font/opentype                  otf
AddType application/x-font-woff        woff

# assorted types                                      
AddType image/x-icon                   ico
AddType image/webp                     webp
AddType text/cache-manifest            appcache manifest
AddType text/x-component               htc
AddType application/x-chrome-extension crx
AddType application/x-xpinstall        xpi
AddType application/octet-stream       safariextz

# ----------------------------------------------------------------------
# gzip compression
# ----------------------------------------------------------------------

<IfModule mod_deflate.c>

<IfModule mod_setenvif.c>
  <IfModule mod_headers.c>
    SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X15|~15|-15)$ ^((gzip|deflate)\s,?\s(gzip|deflate)?|X4,13|~4,13|-4,13)$ HAVE_Accept-Encoding
    RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
  </IfModule>
</IfModule>

<FilesMatch "^(?!.*\.ogg$|.*\.ogv$|.*\.mp4$).+" >

# html, txt, css, js, json, xml, htc:
<IfModule filter_module>
  FilterDeclare   COMPRESS
  FilterProvider  COMPRESS  DEFLATE resp=Content-Type /text/(html|css|javascript|plain|x(ml|-component))/
  FilterProvider  COMPRESS  DEFLATE resp=Content-Type /application/(javascript|json|xml|x-javascript)/
  FilterChain     COMPRESS
  FilterProtocol  COMPRESS  change=yes;byteranges=no
</IfModule>
</FilesMatch>

# webfonts and svg:
  <FilesMatch "\.(ttf|otf|eot|svg)$" >
    SetOutputFilter DEFLATE
  </FilesMatch>
</IfModule>

# ----------------------------------------------------------------------
# Expires headers (for better cache control)
# ----------------------------------------------------------------------

<IfModule mod_expires.c>
  ExpiresActive on

# Perhaps better to whitelist expires rules? Perhaps.
  ExpiresDefault                          "access plus 1 month"

# cache.appcache needs re-requests in FF 3.6 (thx Remy ~Introducing HTML5)
  ExpiresByType text/cache-manifest       "access plus 0 seconds"

# your document html 
  ExpiresByType text/html                 "access plus 0 seconds"

# data
  ExpiresByType text/xml                  "access plus 0 seconds"
  ExpiresByType application/xml           "access plus 0 seconds"
  ExpiresByType application/json          "access plus 0 seconds"

# rss feed
  ExpiresByType application/rss+xml       "access plus 1 hour"

# favicon (cannot be renamed)
  ExpiresByType image/x-icon              "access plus 1 week" 

# media: images, video, audio
  ExpiresByType image/gif                 "access plus 1 month"
  ExpiresByType image/png                 "access plus 1 month"
  ExpiresByType image/jpg                 "access plus 1 month"
  ExpiresByType image/jpeg                "access plus 1 month"
  ExpiresByType video/ogg                 "access plus 1 month"
  ExpiresByType audio/ogg                 "access plus 1 month"
  ExpiresByType video/mp4                 "access plus 1 month"
  ExpiresByType video/webm                "access plus 1 month"

# htc files  (css3pie)
  ExpiresByType text/x-component          "access plus 1 month"

# webfonts
  ExpiresByType font/truetype             "access plus 1 month"
  ExpiresByType font/opentype             "access plus 1 month"
  ExpiresByType application/x-font-woff   "access plus 1 month"
  ExpiresByType image/svg+xml             "access plus 1 month"
  ExpiresByType application/vnd.ms-fontobject "access plus 1 month"

# css and javascript
  ExpiresByType text/css                  "access plus 2 months"
  ExpiresByType application/javascript    "access plus 2 months"
  ExpiresByType text/javascript           "access plus 2 months"

  <IfModule mod_headers.c>
    Header append Cache-Control "public"
  </IfModule>

</IfModule>

# ----------------------------------------------------------------------
# ETag removal
# ----------------------------------------------------------------------

FileETag None

# ----------------------------------------------------------------------
# Stop screen flicker in IE on CSS rollovers
# ----------------------------------------------------------------------

# The following directives stop screen flicker in IE on CSS rollovers - in
# combination with the "ExpiresByType" rules for images (see above). If
# needed, un-comment the following rules.

# BrowserMatch "MSIE" brokenvary=1
# BrowserMatch "Mozilla/4.[0-9]2" brokenvary=1
# BrowserMatch "Opera" !brokenvary
# SetEnvIf brokenvary 1 force-no-vary

RewriteEngine On
RewriteCond %HTTP_HOST !^citylightstours\.com$ [NC]
RewriteRule ^(.*)$ http://citylightstours.com/$1 [R=301,L]
RewriteCond %HTTP_USER_AGENT libwww-perl.* 
RewriteRule .* ? [F,L]

我有一个 MY_Router.php 文件来处理客户 404 页面,想知道这是否错误地设置了 404 http 状态??

MY_Router.php 文件:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class MY_Router extends CI_Router 

    var $error_controller = 'error';
    var $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()
    
        $this->directory = "";
        $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()
    
        $ignore_remap = true;

        $class = $this->class;
        if (class_exists($class))
           
            // methods for this class
            $class_methods = array_map('strtolower', get_class_methods($class));

            // ignore controllers using _remap()
            if($ignore_remap && in_array('_remap', $class_methods))
            
                return;
            

            if (! in_array(strtolower($this->method), $class_methods))
            
                $this->directory = "";
                $this->class = $this->error_controller;
                $this->method = $this->error_method_404;
                include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
            
        
    

    function show_404()
    
        include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
        call_user_func(array($this->error_controller, $this->error_method_404));
    



/* End of file MY_Router.php */
/* Location: ./system/application/libraries/MY_Router.php */

有人可以帮忙吗??

谢谢

【问题讨论】:

我认为它正在查找页面并返回它,但将服务器响应代码设置为 404。它将在 CodeIgniter 中设置在哪里???? 【参考方案1】:

您的路线需要修复:-

$route['en/(:num)/(:any)'] = "content/en/$1";
$route['de/(:num)/(:any)'] = "content/de/$1";
$route['es/(:num)/(:any)'] = "content/es/$1";
$route['it/(:num)/(:any)'] = "content/it/$1";
$route['ar/(:num)/(:any)'] = "content/ar/$1";

请阅读:-

http://www.codeigniter.com/userguide2/general/routing.html

根据您的路由,每种语言都有一个控制器。例如(enController、deController、esController 等...),我假设你没有,你只有一个内容控制器。

您正在寻找的回复可以在这里找到:-

https://github.com/bcit-ci/CodeIgniter/wiki/URI-Language-Identifier

【讨论】:

您好,codenathan,感谢您抽出宝贵时间回复。我读了那篇文章,看不出我的路线有什么问题——它链接到内容类和语言方法。我不认为它指定了不同的内容控制器 - 只是一个具有不同方法的控制器......?无论如何,我删除了对路线语言方面的引用,但我仍然得到 404 服务器响应,并且正确的页面显示为人类自定义页面....有什么想法吗?? 抱歉,我看错了,您能发布您的内容控制器代码吗? 嗨,codenathan,我可以,但我认为这与我的内容控制器无关。一切正常,因为它正确运行并从数据库中获取正确的页面数据并正确显示它。问题是它以 404 而不是 200 的 http 状态显示它。我有一个自定义错误页面,并认为它可能与我为了执行此自定义 404 而拥有的 MY_Router.php 文件有关。我会发布MYRouter 代码...

以上是关于CodeIgniter 路由和 404 自定义错误的主要内容,如果未能解决你的问题,请参考以下文章

codeigniter 自定义 404 页面不起作用

如何使用 Codeigniter 在自定义 404 页面中重定向 404 错误?

自定义 404 未在实时服务器上的 Codeigniter 中显示

如何在 CodeIgniter 中为 403 禁止错误设置自定义页面

Laravel:如何根据路由响应自定义 404 错误

自定义 ASP.NET MVC 404 错误页面的路由