141
if (strstr($_SERVER['REQUEST_URI'],'index.php')) {
    header('HTTP/1.0 404 Not Found');
}

Why wont this work? I get a blank page.

danorton
  • 11,804
  • 7
  • 44
  • 52
  • 1
    Better option would be to send a 404 status and include your custom 404 page immediately. That's what i used to do. – Rocky Oct 25 '12 at 07:05
  • On my PHP server it works perfectly. The above line returns the server's default 404 page. I suppose that this can be configured in the server. – Elmue Oct 07 '14 at 23:25

16 Answers16

309

Your code is technically correct. If you looked at the headers of that blank page, you'd see a 404 header, and other computers/programs would be able to correctly identify the response as file not found.

Of course, your users are still SOL. Normally, 404s are handled by the web server.

  • User: Hey, do you have anything for me at this URI webserver?
  • Webserver: No, I don't, 404! Here's a page to display for 404s.

The problem is, once the web server starts processing the PHP page, it's already passed the point where it would handle a 404

  • User: Hey, do you have anything for me at this URI webserver?
  • Webserver: Yes, I do, it's a PHP page. It'll tell you what the response code is
  • PHP: Hey, OMG 404!!!!!!!
  • Webserver: Well crap, the 404 page people have already gone home, so I'll just send along whatever PHP gave me

In addition to providing a 404 header, PHP is now responsible for outputting the actual 404 page.

Alana Storm
  • 164,128
  • 91
  • 395
  • 599
  • 49
    14 year old girl or not, the little cheesy dialog really made this make sense to me. – rbwhitaker Apr 08 '12 at 19:20
  • Well thank you sir! I finally understood why PHP 404's are working but not working! :)) I was struggling with this for a while now. – Adi Ulici Nov 16 '12 at 18:57
  • 1
    Stack Overflow needs to add functionality to +1 for style. This would get all of the +1's. – Jay Querido Feb 01 '13 at 16:25
  • 30
    That's how documentation should be written! Especially Apache documentation, which I truly hate :) – Harry Mar 05 '13 at 10:05
  • More answers need to be written like this. +1 for dialogue. – ChaseMoskal Jun 23 '13 at 20:59
  • Why can't php read out the error handling documents and redirect directly? Would be so niiiiice! Thanks for your answer buddy! – Noel Widmer Dec 16 '13 at 08:29
  • 4
    bloody brilliantly explained! made my day! – Andrei Cristian Prodan Mar 03 '14 at 09:49
  • On my PHP server it works perfectly. header('HTTP/1.0 404 Not Found'); returns the server's default 404 page. I suppose that this can be configured in the server. – Elmue Oct 07 '14 at 23:28
  • @Yrrol - Any reason this isn't marked as _the_ answer? – Jesse Chisholm Apr 06 '15 at 15:30
  • 1
    For all the people noting they can do this on their server. Nginx supplies a setting that enables it to catch the PHP error state and send the error page configured. It's called [fastcgi_intercept_errors](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_intercept_errors). Not sure if apache has an equivalent setting. – sg3s Oct 12 '16 at 19:40
78
if (strstr($_SERVER['REQUEST_URI'],'index.php')){
    header('HTTP/1.0 404 Not Found');
    echo "<h1>404 Not Found</h1>";
    echo "The page that you have requested could not be found.";
    exit();
}

If you look at the last two echo lines, that's where you'll see the content. You can customize it however you want.

womble
  • 12,033
  • 5
  • 52
  • 66
Evan Fosmark
  • 98,895
  • 36
  • 105
  • 117
74

That is correct behaviour, it's up to you to create the contents for the 404 page.
The 404 header is used by spiders and download-managers to determine if the file exists.
(A page with a 404 header won't be indexed by google or other search-engines)

Normal users however don't look at http-headers and use the page as a normal page.

Bob Fanger
  • 28,949
  • 7
  • 62
  • 78
  • 20
    FWIW, incase of 404, IE returns its standard 'not found' page if the content is short (it assumes the server is just saying 'not found' and decides to display a nicer page to user). – Serge Wautier Dec 27 '11 at 14:06
16

For the record, this is the all-case handler:

<?php
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
header("Status: 404 Not Found");

$_SERVER['REDIRECT_STATUS'] = 404;
?> <!-- 404 contents below this line -->
Silviu-Marian
  • 10,565
  • 6
  • 50
  • 72
14

Load default server 404 page, if you have one, e.g. defined for apache:

if(strstr($_SERVER['REQUEST_URI'],'index.php')){
  header('HTTP/1.0 404 Not Found');
  readfile('404missing.html');
  exit();
}
Kitet
  • 141
  • 1
  • 2
  • its not working, its showing Warning: readfile(404missing.html): failed to open stream: No such file or directory in /var/www/.com/public_html/index1.php on line 61 –  Jan 12 '14 at 09:48
  • 2
    @AMB That's because you have to create that file yourself. – Super Cat Jan 06 '15 at 04:53
  • @SuperCat thanks , now i reread the error and everything is clear now., –  Jan 06 '15 at 06:10
12

Since php 5.4 you can now do http_response_code(404);

rparker
  • 143
  • 1
  • 7
4

Another solution, based on @Kitet's.

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

$_SERVER['REDIRECT_STATUS'] = 404;
//If you don't know which web page is in use, use any page that doesn't exists
$handle = curl_init('http://'. $_SERVER["HTTP_HOST"] .'/404missing.html');
curl_exec($handle);

If you are programming a website that hosted in a server you do not have control, you will not know which file is the "404missing.html". However you can still do this.

In this way, you provided exactly the same outcome of a normal 404 page on the same server. An observer will not be able to distinguish between an existing PHP page returns 404 and a non-existing page.

Earth Engine
  • 10,048
  • 5
  • 48
  • 78
4

try with:

header("Status: 404 Not Found");
header('HTTP/1.0 404 Not Found');

Bye!

Olaf Erlandsen
  • 5,817
  • 9
  • 41
  • 73
2

A little bit shorter version. Suppress odd echo.

if (strstr($_SERVER['REQUEST_URI'],'index.php')){
  header('HTTP/1.0 404 Not Found');
  exit("<h1>404 Not Found</h1>\nThe page that you have requested could not be found.");
}
2
if($_SERVER['PHP_SELF'] == '/index.php'){ 
   header('HTTP/1.0 404 Not Found');
   echo "<h1>404 Not Found</h1>";
   echo "The page that you have requested could not be found.";
   die;
}

never simplify the echo statements, and never forget the semi colon like above, also why run a substr on the page, we can easily just run php_self

Jesse
  • 21
  • 1
1

You're doing it right though it could use some refining. Looks like that's been addressed so let's talk practical application benefits:

An old website of ours that has a large collection of multilingual tech docs was executing this inside an if else conditional:

    if (<no file found>){
        die("NO FILE HERE");
    }

The problem (besides the unhelpful message and bad user experience) being that we generally use a link crawler (in our case integrity) to check out bad links and missing documents. This means that we were getting a perfectly correct 200 no error response telling us that there was a file there. Integrity didn't know that we were expecting a PDF so we had to manually add a 404 header with php. By adding your code above the die (because nothing afterwards would execute and header should always be before any rendered html anyway), integrity (which behaves more or less like a browser) would return a 404 and we would know exactly where to look for missing files. There are more elegant ways of telling the user that there is an error, but by serving a 404 error you are not only notifying browsers and browser-like programs of the error but (I believe-correct me if I'm wrong) are also recording those errors in your server logs where you can easily grep for 404s.

    header('HTTP/1.0 404 Not Found');
    die("NO FILE HERE");
1

Try this:

if (strstr($_SERVER['REQUEST_URI'],'index.php')) {
    header('HTTP/1.0 404 Not Found');
    echo "<head><title>404 Not Found</title></head>";
    echo "<h1>Not Found</h1>";
    $uri   = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
    echo "<p>The requested URL ".$uri." was not found on this server.</p>";
    exit();
}
Soroush
  • 907
  • 1
  • 9
  • 27
1

If you want the server’s default error page to be displayed, you have to handle this in the server.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
0

You know, in my website i created something like this:

        $uri=$_SERVER['REQUEST_URI'];
        $strpos=strpos($uri, '.php');
        if ($strpos!==false){
        $e404="The page requested by you: &quot".$_SERVER['REQUEST_URI']."&quot, doesn't exists on this server.";
        $maybe=str_replace('.php','',$uri);
        $maybe=str_replace('/','',$maybe);
        die("<center><h1>404</h1><hr><h3>$e404</h3><h3>Maybe try <a href=$maybe>www.leaveyortexthere.p.ht/$maybe</a>?</center>");

}

i hope it helps you.

GGG
  • 640
  • 1
  • 9
  • 27
-4

I came up to this problem.. I think that redirecting to a non existing link on your server might do the trick ! Because the server would return his 404:
header('Redirect abbb.404.nonexist'); < that doesnt exist for sure

GorillaApe
  • 3,611
  • 10
  • 63
  • 106
  • 7
    That would also return a 302 if you do that. Better don't redirect your 404's. instead use the 404 status code and display the not found message. – Rocky Oct 25 '12 at 07:02
-17

If you want to show the server’s default 404 page, you can load it in a frame like this:

echo '<iframe src="/something-bogus" width="100%" height="100%" frameBorder="0" border="0" scrolling="no"></iframe>';
cicada
  • 1
  • 1