158

My file .htaccess handles all requests from /word_here to my internal endpoint /page.php?name=word_here. The PHP script then checks if the requested page is in its array of pages.

If not, how can I simulate an error 404?

I tried this, but it didn't result in my 404 page configured via ErrorDocument in the .htaccess showing up.

header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");

Am I right in thinking that it's wrong to redirect to my error 404 page?

Valerio Bozz
  • 1,176
  • 16
  • 32
Eric
  • 95,302
  • 53
  • 242
  • 374
  • Why do you mean it doesn’t work? Did you check the server response header? – Gumbo Sep 04 '09 at 19:32
  • 1
    In answer to your concluding question, yes, it would be a bad idea to redirect all 404s to a real page. This violates the HTTP spec by turning something that shouldn't be there into something that is there. – Lucas Oman Sep 04 '09 at 19:41

10 Answers10

246

The up-to-date answer (as of PHP 5.4 or newer) for generating 404 pages is to use http_response_code:

<?php
http_response_code(404);
include('my_404.php'); // provide your own HTML for the error page
die();

die() is not strictly necessary, but it makes sure that you don't continue the normal execution.

blade
  • 12,057
  • 7
  • 37
  • 38
  • 2
    in which file should i add this? – Julfikar Jun 10 '17 at 08:46
  • 1
    @Julfikar In the php file from which you wish to return a 404 response. For example your php file might have logic which is trying to retrieve a specified id from the database. Didn't find it? Return 404 "Sorry that ID is not found" response to the user. – Harry Wood Jul 29 '21 at 11:44
99

What you're doing will work, and the browser will receive a 404 code. What it won't do is display the "not found" page that you might be expecting, e.g.:

Not Found

The requested URL /test.php was not found on this server.

That's because the web server doesn't send that page when PHP returns a 404 code (at least Apache doesn't). PHP is responsible for sending all its own output. So if you want a similar page, you'll have to send the HTML yourself, e.g.:

<?php
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found", true, 404);
include("notFound.php");
?>

You could configure Apache to use the same page for its own 404 messages, by putting this in httpd.conf:

ErrorDocument 404 /notFound.php
Kzqai
  • 22,588
  • 25
  • 105
  • 137
JW.
  • 50,691
  • 36
  • 115
  • 143
  • Thanks. I'd assumed it used my 404 page. – Eric Sep 04 '09 at 20:17
  • @JW where the above code will be use ? is that code for '.htaccess' file. – Manohar Kumar Feb 20 '15 at 06:13
  • @ManoharKumar above code use in where you want to sent 404 page. In my case, I've used when some one search for a item with it's code, but it's not existed. so I use above code after find out that item not available and I used exit too on 3rd line of this code, for avoid load anything after 404 page. thank you JW, it worked pefectly for me. – Harsha Nov 20 '16 at 10:38
30

Try this:

<?php
header("HTTP/1.0 404 Not Found");
?>
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • 3
    Well a 404 is a 404 both in HTTP 1.0 and 1.1. 1.0 is a safe bet. Cool joke BTW :) +1 – Ates Goral Sep 04 '09 at 20:10
  • @TheEasyLearnAcademy That doesn't really make sense... that's essentially the same as `header("Location: any-url-that-does-not-exist");` - it will trigger a 302 (temporary) redirect to a URL that does not exist so generates a 404 on the redirected (2nd) request. You need to generate the 404 response on the current request. – MrWhite Dec 15 '20 at 00:15
15

Create custom error pages through .htaccess file

1. 404 - page not found

 RewriteEngine On
 ErrorDocument 404 /404.html

2. 500 - Internal Server Error

RewriteEngine On
ErrorDocument 500 /500.html

3. 403 - Forbidden

RewriteEngine On
ErrorDocument 403 /403.html

4. 400 - Bad request

RewriteEngine On
ErrorDocument 400 /400.html

5. 401 - Authorization Required

RewriteEngine On
ErrorDocument 401 /401.html

You can also redirect all error to single page. like

RewriteEngine On
ErrorDocument 404 /404.html
ErrorDocument 500 /404.html
ErrorDocument 403 /404.html
ErrorDocument 400 /404.html
ErrorDocument 401 /401.html
Irshad Khan
  • 5,670
  • 2
  • 44
  • 39
5

Did you remember to die() after sending the header? The 404 header doesn't automatically stop processing, so it may appear not to have done anything if there is further processing happening.

It's not good to REDIRECT to your 404 page, but you can INCLUDE the content from it with no problem. That way, you have a page that properly sends a 404 status from the correct URL, but it also has your "what are you looking for?" page for the human reader.

Eli
  • 97,462
  • 20
  • 76
  • 81
2

Standard Apache 404 error looks like this:

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>  

Thus, you can use the following PHP code to generate 404 page that looks exactly as standard apache 404 page:

function httpNotFound()
{
    http_response_code(404);
    header('Content-type: text/html');

    // Generate standard apache 404 error page
    echo <<<HTML
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>  
HTML;

    exit;
}
Dima L.
  • 3,443
  • 33
  • 30
0

try putting

ErrorDocument 404 /(root directory)/(error file) 

in .htaccess file.

Do this for any error but substitute 404 for your error.

StackedQ
  • 3,999
  • 1
  • 27
  • 41
-1

In the Drupal or Wordpress CMS (and likely others), if you are trying to make some custom php code appear not to exist (unless some condition is met), the following works well by making the CMS's 404 handler take over:

<?php
  if(condition){
    do stuff;
  } else {
    include('index.php');
  }
?>
Mike Godin
  • 3,727
  • 3
  • 27
  • 29
-3

Immediately after that line try closing the response using exit or die()

header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
exit;

or

header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
die();
  • 2
    If you do this, the user sees an empty page. My question was how to send the same 404 page that I specified with `ErrorDocument`, but from PHP. – Eric May 25 '18 at 04:28
  • if you wanna use ErrorDocument Make sure that the path to your custom error file is with respect to the root of the server example: say your virtual path is /folder1/folder2/myhtaccess fromt he root of the server your errordocument will look something like this ErrorDocument 404 /folder1/folder2/my404.html – user5891645 Jun 04 '18 at 03:32
  • `ErrorDocument` does not have any effect after you've already entered the PHP code. [this answer](https://stackoverflow.com/a/1381226/102441) best explains the confusion I faced **9 years ago** – Eric Jun 04 '18 at 06:57
  • I hope your problem is solved by now. On an off subject, I think it's better you didn't redirect with ?name=word_here. Instead, use `$reqpath = strtok("/".trim(substr($_SERVER["REQUEST_URI"], strlen(APP_ROOT)), "/"), "?");` in your page.php file. Coz there is a scenario where one of those pages is expecting a query "name" from the user. – user5891645 Jun 21 '18 at 15:59
-5

try this once.

$wp_query->set_404();
status_header(404);
get_template_part('404'); 
Nikos Hidalgo
  • 3,666
  • 9
  • 25
  • 39
Mani Kandan
  • 59
  • 1
  • 6