Codeigniter & PHP - forcing a 404?

后端 未结 8 1347
予麋鹿
予麋鹿 2020-12-08 10:19

In codeigniter, as you know, a page of the form: /class/function/ID, where class is the controller name, function is the method within the controller, and ID is

相关标签:
8条回答
  • 2020-12-08 10:52

    I had the same problem with you and I found a complete solution for this in CodeIgniter 3. Here I would like to share step by step how to solve it. Of course, we need to support a custom 404 page to satisfy SEO requirement.

    1. Show 404 page for URLs which do not match the schema in routes
      • Add a new Error controller in application/controllers to support a custom 404 page.
    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'); 
        } 
    }
    
    • Add a new custom view error_404.php for 404 page in application/views/errors
    <div>
        <p>We are so sorry. The page you requested could not be found.</p> 
    </div>
    
    • Declare 404_overide in config/routes.php
    $route['404_override'] = 'ErrorController';
    
    1. Show 404 page for URLs which match the schema in routes but point to non-existing resource.
      • Set subclass_prefix in config/config.
    $config['subclass_prefix'] = 'MY_';
    
    • Define your custom Exceptions class in application/core
    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;
        }
    
    }
    
    • Call show_404() wherever you want. Here I created my custom supper model class in application/models and check query results there. Other models will extends the supper model and show 404 page if they could not found a resource.
    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-08 10:53

    show_404() actually sends the proper headers for a search engine to register it as a 404 page (it sends 404 status).

    Use a Firefox addon to check the headers received when calling show_404(). You will see it sends the proper HTTP Status Code.

    Check the default application/errors/error_404.php. The first line is:

    <?php header("HTTP/1.1 404 Not Found"); ?>
    

    That line sets the HTTP Status as 404. It's all you need for the search engine to read your page as a 404 page.

    0 讨论(0)
  • 2020-12-08 10:55

    Only follows these steps:

    Step 1 Update your application/config/routes.php file

    $route['404_override'] = 'error/error_404';
    

    Step 2 Create your own controller in controllers folder 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);
    }
    }
    ?>
    

    Step 3 Create your view in views folder 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>
    
    0 讨论(0)
  • 2020-12-08 10:57

    Yes show_404() WILL send out a 404 but it looks like hell. There have been a few hacks suggested here, but why hack when you can use built in features?

    Upgrade to CI 2.0 and you'll be able to use the amazing:

    $route['404_override'] = 'errors/error_404';
    

    Then you can have a general errors controller without having to worry about trying to load views, libraries and helpers WY too early in the CI instance to function properly.

    0 讨论(0)
  • 2020-12-08 10:58
            $this->output->set_status_header('404');
    

    to generate 404 headers.

    0 讨论(0)
  • 2020-12-08 10:58

    Create controller in your application/controllers folder.

    class Error extends Controller
    {
    function error_404()
    {
        $this->load->view('error');
    }
    }
    

    Then in your application/library extend the Router class by creating 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);
            }
        }
    }
    

    }

    If the page does not exist, it will be routed to error controller

    0 讨论(0)
提交回复
热议问题