Custom 404 error pages with CodeIgniter

Quick and simple way to use a standard controller method for 404 error pages.

Create controller/method for 404 errors

system/application/controllers/error.php

<?php
class Error extends Controller {
 
	function error_404()
	{
		$this->output->set_status_header('404');
		echo "404 - not found";
	}
}

Add MY_Router.php

system/application/libraries/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 */

Notes

Controllers using remap()

They are ignored, since it's not possible to know for sure if it's a 404. However, if you wish to throw a 404 anyway if the URL parameter doesn't match an existing method, change $ignore_remap to false.

Call 404 page manually from a controller

$this->router->show_404();

Example of use case: /store/product/3 is called, product() exists but there's no product 3.

Note: replace all occurrences of $this in the error method by $CI:

$CI =& get_instance();
$CI->output->set_status_header('404');
 

Feedback

.. but CI already has a 404 template? " 404 Page Not Found The page you requested was not found. "
bjorn
Feb 21, 2009
#1
Yes CI has already, but this custom router let you use your own methods and views for the 404 pages. CI won't allow many things in 404 pages and that's really annoying, so this lib is really useful, thanks for sharing !
Chris
Feb 21, 2009
#2
FYI: Been down this path before. This doesn't catch the 404's when a method is not available in a controller. 404's from methods are handed off to another lib via the CI core (hint: exceptions) :)
solidcode
Mar 1, 2009
#3
Solidcode: that's what check_method() does.
Jérôme Jaglale
Mar 1, 2009
#4
thank you! very good!!
John an
Mar 11, 2009
#5
Hi, Great script, very handy. Just wondering if it can be modified for error_db and the other error pages in the "errors" directory? Would be very handy indeed. Thanks again, Rob.
Rob
Mar 22, 2009
#6
Hello, thanks by source code....
FUEL SIRPA MAMANI
Mar 30, 2009
#7
hello, big big big big Thanks for sharing this ROUTER method for CUSTOM 404. Because having default - means mostly everybody knows you are using CI. Thanks !
huglester
Apr 8, 2009
#8
Thanks for sharing. But how can i make it work with you internationalization librairies? If i put a language in the URL that is not present, the error 404 does not work...
Snap
Apr 19, 2009
#9
Default behaviour of the i18n library: when a language is not found in the URL, redirect to $default_uri (at least, that's what was supposed to happen. There was a bug, that I just fixed). If you want to generate a 404 error instead: in MY_Language.php, in the constructor MY_LAnguage(), just remove the "else" statement (and the code in it).
Jérôme Jaglale
Apr 20, 2009
#10
Vraiment enorme ! merci
Hilton
May 26, 2009
#11
I added a line to your IF clause in the check_method() function. Otherwise, if someone is using _remap() in a controller, this will override it and throw an error. Here's my updated version:
function check_method()
	{
		$class = $this->class;
		if (class_exists($class))
		{
			if (! in_array('_remap', array_map('strtolower', get_class_methods($class)))                     // <-- Allows me to use the _remap function in my controllers without throwing a 404 error 
                && ! 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);
			}
		}
	}
Chris
May 28, 2009
#12
Thank you very much Chris, I updated the code.
Jérôme Jaglale
May 28, 2009
#13
I am having some issues with this 404 setup, any help? Example... http://lakesideohio.com/about (valid controller, page works) http://lakesideohio.com/about/nope (CI error) http://lakesideohio.com/about/main (valid controller, page works) http://lakesideohio.com/about/main/nope (multiple CI errors, 'main' is the default controller)
Rob
May 29, 2009
#14
wow it rocks man!! so easy and well working!! GREAT THANKS!!!!!!!!!!!!!!!!1
wow
Jun 26, 2009
#15
Sorry guys I'm new to CI :-( Can anyone explain to me what to do after creating these two files and puttin them into their locations?? I've simply copied and pasted the two snippest above and created the two files but the error page stays the same CI Template!! Any help is greatly appreciated
Samara
Jun 30, 2009
#16
It's awesome! Thank you very much!
GiN
Aug 2, 2009
#17
So, does this still send a 404 header or just redirect to the error controller? Would I want to send my own 404 header in this case? Thanks.
Jim
Aug 12, 2009
#18
Yes, you'd want to send your own:
$this->output->set_status_header('404');
echo "404 - not found";
Jérôme Jaglale
Aug 12, 2009
#19
Thanks, Jérôme! One more question: How do I make this work with the show_404('page') method (http://codeigniter.com/user_guide/general/errors.html)? Do I need to extend CI_Exceptions?
Jim
Aug 17, 2009
#20
Thanks for this, http://dzineblog.com/2008/11/custom-error-404-pages.html here is some link for nice custom error 404 pages.
Zoran
Aug 21, 2009
#21
Hi Jerome, thank you for the great class! I'm trying to trigger the 404 page without redirecting from within a controller but don't understand how to get it to work: I'm using custom routes with a regular expression -> $route['stuff/([a-z_-]+$)'] = "stuff/viewByType/$1"; if the visitor types the url "mysite.com/stuff/noexists" I need to trigger the 404. For now I can only get it to work by using "redirect('error/error_404', 'location');" and for usability this is not good as it changes the url (yes i'm picky^^)... Any idea on this? Thanks for your time and great libraries
Erik
Sep 6, 2009
#22
Ok, nevermind just found a way :) May not be the correct way to do it but it works : if('condition is false') { MY_router::_validate_request(NULL); }
Erik
Sep 6, 2009
#23
Well, no I jumped the gun... my question still holds :)
Erik
Sep 6, 2009
#24
Erik, you could use the code that you have in error_404() in your "stuff" controller (when there's a 404). If you don't like the code duplication, you could then externalize that code in a helper or library.
Jérôme Jaglale
Sep 8, 2009
#25
Thank you for your response Jérôme ! I'm fairly new to frameworks so making a helper or library is not (yet) an option for me and as you guessed I don't like code duplication (which is one of the reasons why I came to CI in the first place). I finally opted for an error method in my controller as you suggested. Once again thank you for your help and great libraries :)
Erik
Sep 12, 2009
#26
Thank for your contribution, but to accomplish same, I have simply placed a 'header('Location: http://example.com/error/404')' in CI default error_404 template
KSE
Sep 16, 2009
#27
Thank you KSE, but the point here is to not change the URL.
Jérôme Jaglale
Sep 16, 2009
#28
Nice. The standard CI 404's are indeed rather limited in functions so this is a good solution
Steven Dobbelaere
Sep 29, 2009
#29
Very nice. Works like a charm. I will be sure to comment here if I find any bugs!
Sotta
Oct 28, 2009
#30
hi, i just create the two files and follow the instruction to where it should be placed. i don't know, why it does not take effect when i try to browse a not existing page on my site. it just displays the default error page of CI. Please need some help. :(
Rhiane Caña
Oct 29, 2009
#31
Thanks for the blog... Great help... :) i got an idea because of your blog, i just integrate some of your codes to CI Router... and it works... Thanks a lot.... :)
Rhiane Caña
Oct 30, 2009
#32
Thanks Jérôme for the code, however I think for my current situation KSE's solution is best. I will most likely use in other projects though!
Nick
Nov 7, 2009
#33
Thank you Nick, but a problem with KSE's solution is that you don't let your visitor know what is the wrong URL. And you can't log it either.
Jérôme Jaglale
Nov 7, 2009
#34
Jérôme, We know it is a 404 error, and we could get the URL that they tried to reach. Thus really we could create a link that looked like this: http://example.com/error/404/badurl.com along with any other information... I am now more curious on if this is a good way to do it, or would this be considered bad practice. My thing is, it seems like a lot less code this way, one bad side is you have one more page request... Thoughts?
Nick
Nov 8, 2009
#35
Jérôme, just wanted to say thank you, thank you, thank you! This class works perfectly and is exactly what I needed. I was preparing to write one myself and dreading the thought. Thanks again!!
fildawg
Nov 13, 2009
#36
I was sometimes getting "Cannot redeclare class Error" errors, so I wrapped the Error controller with "if (!class_exists('Error')) { }" and she's all sweet now mate, hey. :)
James from Oz
Nov 16, 2009
#37
Works great, however how would you make this compatible with the show_404() function? You've hinted at it above but can you give me an example of how to do it because i'm stumped.
Steve
Nov 23, 2009
#38
Great script. Worked instantly with no messing around. Top work.
Paul
Nov 25, 2009
#39
Agree with @Paul
klanjabrik
Nov 25, 2009
#40
Great script, thank you!
Summer
Dec 2, 2009
#41
If you want your new, beautiful custom 404 page to show up when there are disallowed characters in the URL, check out this thread: http://codeigniter.com/forums/viewthread/50154/
Summer
Dec 6, 2009
#42
THANK YOU Jérôme Jaglale!!! THAT LINE IS EXTREMELLY IMPORTANT BECAUSE IF YOU HAVE A CUSTOM 404 THAT RETURNS 200 IT IS BAD!!! REAL BAD!!!

Dec 12, 2009
#43
Thanks for this. One correction: You need to reset the directory to the directory where your error handler class is - in case you encounter the error inside a subdir. If you do not the error class will not be found function error_404() { $this->directory=""; $segments = array(); $segments[] = $this->error_controller; $segments[] = $this->error_method_404; return $segments; }
Ben
Dec 13, 2009
#44
And of course also in the check_method() set $this->directory="" ..
Ben
Dec 14, 2009
#45
Deprecated: Assigning the return value of new by reference is deprecated in C:\xampp\htdocs\ci-ext\system\codeigniter\Common.php on line 123 Deprecated: Assigning the return value of new by reference is deprecated in C:\xampp\htdocs\ci-ext\system\codeigniter\Common.php on line 129 i m getting thease error please help:-(
siddesh
Dec 15, 2009
#46
why thats complicated way? without framework it is a 5 lines of code :)
oh
Dec 20, 2009
#47
good work, thanks =). CI needs more users like you, since its own staff isn't doing much to improve it =/ Sometimes I can't believe it still doesn't have native features like the one you added here Thanks again
horape
Jan 16, 2010
#48
i love CI :)
master
Jan 20, 2010
#49
Wow! This is already amazingly helpful! I will be using this script on every CI project from now on! Thanks!
Matt
Jan 27, 2010
#50
Hi! Big thanks for this. Do you have a similar solution for handling other error types as well. DB, PHP & General ? Thanks a lot!
Jay
Jan 31, 2010
#51
An Error Was Encountered

Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.

I seem to be getting that error when having my controller in a sub directory and I tried setting $this->directory = ''; but then I receive an error for any include file that has been used.
Topher
Feb 15, 2010
#52
So I fooled around with this a little and by adding $this->directory = '' to error_404() before the return, Errors do not get sent to an error page inside a subfolder containing a controller, but rather to the main error controller. Hope this makes sense and helps. =) cheers

Topher
Feb 15, 2010
#53
Nice! Thank you.
bie
Feb 16, 2010
#54
Excellent. Thanks for having this information up. Made it quick and easy to implement.
Darren
Mar 16, 2010
#55
A warning: This does not work with gzip compression, probably due to the way buffering with gzip output is handled, this breaks it. When gzip is activated, the user gets:
Content Encoding Error
The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.
khromov
Mar 26, 2010
#56
This works great however I am having an issue when using a default controller in a subfolder.

Route:
$route['default_controller'] = "home";

I have the following directory structure:

/controllers/home.php
/controllers/admin/home.php

If I attempt to access http://myurl.com/admin/non-existent I get a 'Fatal error: Cannot redeclare class Home in ...'. I am guessing I need to alter the _validate_request() function, specifically here:

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
{
// Need to add something here?
}
}
Jason
Apr 28, 2010
#57
Nevermind my previous post, user error. $this->error_controller was set to the same default controller, home. My fault!
Jason
Apr 28, 2010
#58
good contribution tanks
Alberto Arroyo
Apr 29, 2010
#59
Thanks for this, it was a big help!
morehawes
May 31, 2010
#60
Copy/paste ... 1 problem less! Thank you!
Peppe
Jun 30, 2010
#61
My CI is using _remap function, but I copy the check_method() function not working with mine. I am not sure the in_array search for _remap got what use? it didn't call for the function to remap it.

in my _remap() function, what I do is str_replace( "-", "_", $method );

I not sure what is the reason for using these line of code
if ($class == 'doc')
{
return;
}


but what I did is change to this, function

function check_method()
{
$class = $this->class;
if (class_exists($class))
{
//_remap function
$this->method = str_replace( "-", "_", $this->method );

if ( ! 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);
}
}
}

Then it work perfectly~
Shiro
Jul 8, 2010
#62
really works nice! anyway i can not make it to work all the times.
if i have valid url like this:
/products/detail/product_id
and this id exists in the database, then the page is displayed correctly
if my url is:
/products/blablabla
it gives me 404 (that is what i want), because there is not a function blablabla()
but if i have a url like:
/products/detail/blablabla
it checks for a product with id=blablabla, there is no such a product in my db, so i have a blank page.
yes, i know i can check if the product id is valid, but anyway if it is not, how to call this 404 magic anyway?
BuKToP
Jul 12, 2010
#63
Shiro: thank you. The useless code has been removed. There's a new note about remapped controllers.

BuKToP: good point. A method has been added for that, with a note on how to call it. Thank you.
Jérôme Jaglale
Jul 12, 2010
#64
Ben(#44, #46): thank you! That's fixed.
Jérôme Jaglale
Jul 12, 2010
#65
I use this on my controller:

$this->router->show_404();

Here's the error message I got when I was trying to access the controller:

Fatal error: Using $this when not in object context in D:\wwwprojects\....\....\application\controllers\error.php on line 12

I have created the files as the above instructions. Did I miss something?
Hour Glass
Jul 13, 2010
#66
Problem is solved. I've just commented the line "error_reporting(E_ALL);" at index.php on my root folder and it worked successfully. Thanks for the code.
Hour Glass
Jul 13, 2010
#67
Simply great! Really ... Not it is the perfect piece of code. Thanks a lot!
BuKToP
Jul 13, 2010
#68
@Hour Glass, the same problem here ... Maybe Jérôme will give us a better solution? Hiding an error does not mean fixing it ;]
BuKToP
Jul 13, 2010
#69
Hour Glass and BuKToP: thank you, there's a new note for that.

Just FYI, another way of calling the error code "manually":
- create an helper function with the code of your error method
- call it from your error method (so you have the code in only one place)
- call the helper function directly from other controllers
Jérôme Jaglale
Jul 13, 2010
#70
Thanks, Jérôme! But anyway I don't understand how to fix it. To use CI but ... where?
BuKToP
Jul 14, 2010
#71
Wherever you have $this in your error method:

Example: replace
$this->load->view('my_error');
by
$CI->load->view('my_error');
Jérôme Jaglale
Jul 14, 2010
#72
Thanks again, Jérôme! But I am following strictly your steps and I don't have
$this->load->view('my_error');

I have MY_Router.php, and I have controllers/error.php with the code, given by you:
function error_404()
{
$this->output->set_status_header('404');
echo "404 - not found";
}
In my controller products.php I have:
if ($query->num_rows() > 0)
{
// Some code when we have this row ...
}
else
{
$this->router->show_404();
}

And as you see, I don't use $this->load
Please, give me a hint about that.
BuKToP
Jul 14, 2010
#73
And if I comment the line with $this like that:
function error_404()
{
//$this->output->set_status_header('404');
echo "404 - not found";
}
It works perfect :)
Someone please, explain why we need this line at all...
BuKToP
Jul 14, 2010
#74
Sorry for posting again, but ... with the last changes here, I think I have some regression :(

my-site.com/blabla - not existing model/controller ... not showing 404 (and it should)
my-site.com/products/ - existing controller, works (products list page)
my-site.com/products/blabla/ - not existing function - not showing 404 (it should)
my-site.com/products/detail/ - showing 404, as no ID is added, works as expected
my-site.com/products/detail/22 - existing ID, showing the page
my-site.com/products/detail/2345678 - not existing ID, showing 404 as it should.
BuKToP
Jul 14, 2010
#75
Last post, I promise :]
Anyway ... When I comment this line:
//$this->output->set_status_header('404');

It works really perfect! I am... just ready to delete it :]
Please, someone ... what is the problem with this single line?
BuKToP
Jul 14, 2010
#76
BuKToP: replace
$this->output->set_status_header('404');
by
$CI =& get_instance();
$CI->output->set_status_header('404');
Jérôme Jaglale
Jul 14, 2010
#77
Well, Jérôme... The result is ... at least now it is always the same. The strange thing is that the echo is not displayed. Tried with IE, Opera, FF, Safari, Chrome. I am getting a standard browser error, but when I right click -> view source, I can see the echo in the source, e.g. "404 - not found".
Seems like when it sets this status header, It will not display anything. I can see in the source, but not in the browser itself.
BuKToP
Jul 14, 2010
#78
BuKToP: I can't reproduce this problem (except in Chrome which is a special case: http://perso.hirlimann.net/~ludo/blog/archives/2008/09/chrome-and-404s.html

Could you send me your source code so I can have a quick look? My email is on the home page.
Jérôme Jaglale
Jul 14, 2010
#79
Good link, Jérôme ... There is also a comment there that IE does exactly the same :]
When I added more text, it is perfect now! Thanks a lot!
BuKToP
Jul 14, 2010
#80
any version for ci2 ?
z3phir
Jul 16, 2010
#81
Great job !
ThallisPHP
Jul 24, 2010
#82
@z3phir, I am using it exacly with CI 2.0 without any problems...
BuKToP
Jul 26, 2010
#83
I had to add exit() in the error.php file for this to work properly. So right after I echoed out "404 - not found" I did another line and put exit();

Otherwise I was getting the 'Cannot redeclare class Error' error when using remap and also it was displaying the rest of my page even after echoing the 404 message.
Phire_SK
Jul 30, 2010
#84
after trying to get this working in all situations, I kind of gave up, but great work.

Instead, I realized you can just customize errors/error_404.php and you can use &lt;? $CI =& get_instance(); ?&gt; to use all of codeigniter's functions. So basically it is the same as having a controller. You can even test URL segments to make custom messages in the 404 page.

Anyway, just thought I'd mention this way too since I found it not so bad.
Phire_SK
Jul 30, 2010
#85
Phire_SK: I just tested $CI =& get_instance(); and then load a view in errors/error_404.php and it seems to work indeed. Thank you for sharing!
Jérôme Jaglale
Jul 30, 2010
#86
So what exactly happens that $this is no longer an instance of CI core or whatever?

That last gotcha is really annoying because you can't just drop in controller functions that might be flying around elsewhere in your application.
webPragmatist
Aug 4, 2010
#87
webPragmatist: it's only if you need to use
$this->router->show_404();

in a normal controller.

In that case, that controller has already been instantiated and at that point it's not possible to instantiate the error controller and associate it to $this.
Jérôme Jaglale
Aug 4, 2010
#88
Hey guys, i cant get it to work fully.

my code where i get my problems :

function content(){
$url_key = $this->uri->segment(3);
if($url_key==NULL)
{
$this->router->show_404();

}
$data['content'] = $this->content_model->get_one_page(NULL, $url_key);
if($data['content']===FALSE )
{
$this->router->show_404();
}else{
$data['main_content'] = "frontend/content_single_view";
$data['header']['page_title'] = $data['content']['name'];
$this->load->view('frontend/includes/template', $data);
}

}

i will just return a blank page (no html) wen i go to :
http://cms.it-traffic.nl/view/content/asfd
or
http://cms.it-traffic.nl/view/content/

This works:
http://cms.it-traffic.nl/view/content/over-ons - no 404, correct
http://cms.it-traffic.nl/view/asdf - shows 404, correct

so it goes wrong when i call it manually... with :
$this->router->show_404();

Anny idea's how to fix this?

Thx !
Nico
Aug 5, 2010
#89
Hi,

Thanks for posting this out. Quick question before trying this out and getting my hopes up too much - what licence is this code released under?

Juliette
Juliette
Aug 17, 2010
#90
No specific licence Juliette, feel free to use it in any way you want.
Jérôme Jaglale
Aug 17, 2010
#91
Hi, anyone can help me with this problem?
----

load->model('user_db'); } function index() { $login=array(); $this->parser->parse('login/login',$login); } function act() { $user=$this->input->post('user_name'); $pass=$this->input->post('pass'); if($this->user_db->validate_user_login($pass,$user)==0) { redirect('?c=login', 'refresh'); } else { $data=$this->user_db->validate_user_login($pass,$user); //$this->session->set_userdata('some_name', 'some_value'); //echo $data[0]['USER_NAME']; $this->session->set_userdata('ID_USER', $data[0]['ID_USER']); $this->session->set_userdata('USER', $data[0]['USER_NAME']); $this->session->set_userdata('NAME', $data[0]['NAME']); $this->session->set_userdata('PREV', $data[0]['ID_ROLE']); $this->session->set_userdata('UNIT', $data[0]['ID_UNIT']); redirect('?c=home', 'refresh'); } } } ?&gt;
A PHP Error was encountered

Severity: Warning

Message: Cannot modify header information - headers already sent by (output started at x:\xampp\htdocs\xyz\system\application\controllers\login.php:39)

Filename: codeigniter/Common.php

Line Number: 360
404 Page Not Found

The page you requested was not found.

----
thanks,
sfdn
sifdy
Aug 24, 2010
#92
This is probably a dumb question, but how easy/hard would it be to use this same approach for database errors?
Chris
Sep 30, 2010
#93
in the new CI2 you can just use $route['404_override'] to specify your custom 404 controller
amos
Nov 9, 2010
#94
Hi,
i'm trying to get the CI error pages to display in IIS7. they are refusing to display.
StillMonkey
Nov 11, 2010
#95
Hi, I'm new to CI and PHP, why not just use PHP redirect to redirect the user to a page you made else where?
nxdu
Nov 22, 2010
#96
The method I tried is the location header redirect, it worked, so I was wonder why not use this? Thanks.
nxdu
Nov 22, 2010
#97
Clever Method .. It works perfectly
/m\.(-_-). /m\
[][][][][][]
Christopher Cuizon
Nov 23, 2010
#98
Awesome, thanks!
Amanda
Dec 17, 2010
#99
No all of you are wrong. You need to delete such strings "//include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);" (line 96 and 103 in MY_Router). I need to show error INSIDE my website design template, that used lots of function, database, views. My controller called usr. When error 404 inside usr i get error "Fatal error: Cannot redeclare class Usr in /home/h11580/data/www/apokalipsis-2012.ru/system/application/controllers/usr.php on line 2". So i fixed you code. look at realtime http://apokalipsis-2012.ru/usr/yourMothers_pussyFunction/111/1/1/1/3/
director
Jan 1, 2011
#100
this is very helpful, thanks
Cipher
Mar 11, 2011
#101
sorry, how to load view file in the file "error.php"?
asdf
May 13, 2011
#102
paraphrase my previous question:

in application/errors/error_404.php file i wanna load another view files.

how to do this?
asdf
May 13, 2011
#103
Jerome,

i got this error, seems like CI failed when read MY_Router.php

"Fatal error: Call to undefined method CI_Router::show_404() in D:\xampp\htdocs\kaskushotthread\application\controllers\page.php on line 28"

i called "$this->router->show_404();" directly from my controller.

any idea for this problem?i'm using ci 2.0.2

Thanks
ghprod
May 19, 2011
#104
Very very cool your solution.
Very useful. Thanks for sharing.

Congrats

@jeff_drumgod
Jefferson Rafael
Jun 15, 2011
#105
its the site where this application is using and check it how accurately its working and the outlook of this site is so attractively <a href="http://www.stayconnecting.com">Codeigniter example Site </a>
umer singhera
Jun 28, 2011
#106
Hi I just wondering if this works for the new version of CI 2.02 because I implemented and its not working, any help I appreciate!
Thank you
Kgirl
Jul 8, 2011
#107
@Kgirl I also need to use it in CI 2.02 so I tell you when it works :)
kewix
Aug 23, 2011
#108
hello there

this code is not working in my application [Codeigniter 2.0.2]

Plz help me

Thanks in advance
basheer
Sep 21, 2011
#109
Not working for me, would love an update! [Codeigniter 2.0.3]
Thomas Reggi
Sep 28, 2011
#110
The following should work:

MY_Router.php:10 -> update to -> parent::__construct();


I think that should be enough.
Wayn
Oct 10, 2011
#111
In CI 2, place MY_Router.php under /application/core/ and change

MY_Router.php:10 -> update to -> parent::__construct();

as Wayn said.
Juan
Oct 13, 2011
#112
Great work! Will use you method on kanji.ligona.org
Bill
Oct 22, 2011
#113
Thanks, works great.
Arjen
Oct 28, 2011
#114
Thanks for this post, it was a great help. I made one amendment though, I'm using callbacks in my form validation scripts, and I don't want those functions to be available directly. Since they all have the underscore prefix to make them "private", I changed the check_method() code like this:

if (substr($this->method, 0, 1) == '_' || ! in_array(strtolower($this->method), $class_methods))
{
/* If the method starts with '_' then it is a private method (e.g. a validate callback method) and should
* also return a 404.
*/
$this->directory = "";
$this->class = $this->error_controller;
$this->method = $this->error_method_404;
include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
}

If you don't do this you'll find that requests to your callback methods get sent to the default 404 error page.
Dan Searle
Nov 3, 2011
#115
Just one - maybe dumb - question...
I've been researching about 404 in CI for good 3 days trying to find the best solution and this question is keep coming back: What about restyling existing CI error page?
Regards
Tomek
Nov 11, 2011
#116
Anybody get this to work with HMVC?
Mike
Nov 15, 2011
#117
I used another solution and it's work, so what are your opinion about this solution?

My solution is:

replace line 101 in system/core/Exceptions.php
echo $this->show_error($heading, $message, 'error_404', 404);

by:
header('Location: test/page_404');

and in my controller test, I create a new function named page_404
function page_404()
{
$this->data["site_title"] = "404 Error - ".$this->siteTitle;
$this->data["page_title"] = "404 Error";
require("include_tpl.php");
$this->data['page_content'] = "404 Error, Page Not Found... Sorry for this inconvenience.<br /><br />You can start again by clicking <span class='menu1'><a href='".base_url()."main'>HERE</a></span>.";
$this->load->view( "tpl_template" , $this->data );
}
and it's working for me.
When I have an 404 error, I get customed page_404.
MOE
Nov 26, 2011
#118
I used this, however, it does not give 404 to google. It returns 200. Is it ok?
Fortis
Dec 8, 2011
#119
Very cool - made small adjustments for current Codeigniter:
- Error class must extend CI_Controller

and all works fine! Thanks
fjckls
Jan 25, 2012
#120
I am confused. I created error.php and MY_Router.php as instructed. I updated the constructors to support the latest CI. But when I put in a bogus URL I get the default 404 page still. Is there something else I need to do?
Dougw
Mar 12, 2012
#121
The default 404 page works fine, but if I call the $this->router->show_404() function in a controller, nothing happens... The controller executes the hole code below the function call. Any solutions? [CI 2.1]
dome
Apr 4, 2012
#122
Thank you! very helpful indeed
Kass
May 9, 2012
#123
Any tips on how to modify this for a custom route?

I am using a custom route to completely hide my controller (only one controller - had to keep with previous url scheme).
With no controller segment I get this:

http://mysite.com/[controller-removed]/false-method // shows my custom error http://mysite.com/[controller-removed]/correct-method/false-id // shows default error
http://mysite.com/controller-restored/correct-method/false-id // shows custom error

I'd like to show my custom 404 in all instances if possible. Other than my [special] case it is working great on CI 2.1!
Needle
May 26, 2012
#124
Is there any way to stop this functionality temporarily?
Naresh Kumar
Jul 9, 2012
#125
For anyone who has issues with $this when not in object context, or who needs the __construct to be run on their controller class -- instead of messing about with $CI =& get_instance(); -- replace the show_404 method of the MY_Router class with:
function show_404()
{
include(APPPATH.'controllers/'.$this->fetch_directory().$this->error_controller.EXT);
$error_controller = new $this->error_controller;
call_user_func(array($error_controller, $this->error_method_404));
}
John Smith
Jul 31, 2012
#126
Woot, thanks, it works for CI 1.7 (yup, the site i'm working on is getting too old and we tried to update it and nothing works so we're fixing some stuff until we set up a new site running wordpress (more appropriate for the clients).

Thanks alot for this MY_Router.php hint :D
Gabriel Le Breton
Aug 10, 2012
#127
I was also have a "$this when not in object context" issue along with the _remap method. The solution that worked for me was to have my Error class use static vars.

class Error extends CI_Controller
{
private static $_CI = NULL;

/**
* A unique constructor method to this class
*/
function _construct()
{
$instance =& get_instance();

self::$_CI = $instance;
}

/**
* Show a 404 page
*/
function error404()
{
Servererror::_construct();

self::$_CI->output->set_status_header('404');

self::$_CI->load->view('error/404', self::$_CI->data);
}
}
Devin Dombrowski
Mar 11, 2013
#128
thx great work
buff
Jun 22, 2013
#129
thanks! its possible, modify it to HMVC ?
Jonathan
Jul 16, 2013
#130
its not working
rakesh123
Jul 2, 2014
#131