2

Typical scenario:

  1. DB items are displaied in page http://...?item_id=467
  2. User one day deletes the item
  3. Google or a user attempts to access http://...?item_id=467
  4. PHP diggs into DB and sees items does not exist anymore, so now PHP must tell Google/user that item is not existing via a 404 header and page.

According to this answer I undertstood there is no way to redirect to 404 Apache page via PHP unless sending in code the 404 header + reading and sending down to client all the contents of your default 404 page.

The probelm: I already have an Apache parsed custom 404.shtml page, so obvioulsy I would like to simply use that page. But if i read an shtml page via PHP it won't be parsed by Apache anymore.

So what do you suggest me to do?

Is there maybe some trick I could use palying with htaccess too?

Thanks,

Community
  • 1
  • 1
Marco Demaio
  • 33,578
  • 33
  • 128
  • 159

4 Answers4

4

Hmm. Two ideas come to mind:

  • Redirect to the 404 page using header("Location:...") - this is not standards-compliant behaviour though. I would use that only as a last straw

  • Fetch and output the Apache-parsed SHTML file using file_get_contents("http://mydomain.com/404.shtml"); - also not really optimal because a request is made to the web server but, I think, acceptable in most cases.

I doubt there is anything you can do in .htaccess because the PHP script runs after any rewrite rules have already been parsed.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 2nd solution is great! +1 thanks! True that another request is made to the server, but at the end of the day it's a 404 page so it won't frequently happen that final user ends up on these type of missing pages, even if they take a bit more to show I think it's acceptable. – Marco Demaio Nov 20 '10 at 11:14
  • @Marco yup, I think so too. Also, the request should be dealt with locally so it will be very fast. One afterthought, for optimum security use `file_get_contents()` instead of `include()` so there can't be PHP code in the shtml file, I'll edit that in. – Pekka Nov 20 '10 at 11:16
  • @Pekka, I thought to use `file_get_contents`, I didn't know I could use `include` for this, so thanks also for that hint even if yiu say is lees secure. – Marco Demaio Nov 20 '10 at 11:20
  • @Marco both methods are fine, but `include()` would execute any PHP code inside the SHTML file which is good to avoid if it's not needed. – Pekka Nov 20 '10 at 11:22
  • @Pekka: maybe readfile in this case is even better as suggested by Gumbo: http://stackoverflow.com/questions/1621972/php-navigate-to-error-page/1621975#1621975 – Marco Demaio Nov 20 '10 at 12:04
  • 1
    @Pekka: it works because I call readfile on the full http url `("http://...")` so the server calls the page that is parsed 1st by Apache and it's the Apache output that is retrieved by my script. It's the same of file_get_contents, but I don't need to output the buffer. – Marco Demaio Nov 22 '10 at 17:52
2

IF you are using apache mod_php, use virtual('/404.shtml'); to display the parsed shtml page to your user.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
0

I was looking exactly for something like you needed, so you have a page:

http://example.com/page?item_id=456

and if later you want that if item is missing you are redirected to:

http://example.com/page_not_found?item_id=456

In reality I found it is much more maintainable solution to just use the original page as 404 page.

<?php
    $item = findItem( $_GET['item_id']);
    if($item === false){
        //show 404 page sending correct header and then include 404 message
        header( $_ENV['SERVER_PROTOCOL'].' 404 Not Found', true );
        // you can still use $_GET['item_id'] to customize error message
        // "maybe you were looking for XXX item"
        include('somepath/missingpage.php');
        return;
    }

    //continue as usual with normal page

?>

So if item is no longer in the DB, the 404 page is showed but you can provide custom items in replace or error messages.

CoffeDeveloper
  • 7,961
  • 3
  • 35
  • 69
0

I was trying to do this exact same thing yesterday.

Does Pekka's file_get_contents/include result in a 404 status header being sent? Perhaps you need to do this before including the custom error page?

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

You can test using this Firefox extension.

David Oliver
  • 2,424
  • 1
  • 24
  • 37
  • No, `file_get_contents` does not send the 404. You have to do that manually as you show. – Pekka Nov 20 '10 at 12:05
  • The soluiton is in my question in the part where I say "According to this answer I undertstood..." just follow the link. – Marco Demaio Nov 20 '10 at 12:06