使用mod_rewrite模式匹配errorDocument规则

Having a little difficulty implementing error handling for 404 to my site. Normally this is not an issue but in this case the set up is different.

I am having to use pattern matches in my .htaccess file for URL rewrites i.e. RewriteRule ^([^/]+)\/$ and RewriteRule ^products\/([^/]+)\/([^/]+)\/$ this is due to the site having a CMS controlled by other users who can add new pages I.e. www.yourdomain.com/pagename "pagename" being any new page.

Any URL typed in lets say "/about" will match RewriteRule ^([^/]+)\/$ then be checked in a database to find a match, if a match is found then the user is redirected to the correct page, if no match then I could redirect the user to a specific page or set a http status code.

Only problem with that is I would want to preserve the incorrect URL and a PHP redirect would overwite that.

code:

ErrorDocument 403           /errors.php?error=403
ErrorDocument 404           /errors.php?error=404
ErrorDocument 500           /errors.php?error=500
ErrorDocument 503           /errors.php?error=503

RewriteEngine                                  On

RewriteRule ^([^/]+)\/$                     ?cat=generic&page=$1 [L]
RewriteRule ^products\/([^/]+)\/([^/]+)\/$  ?cat=product&page=$2 [L]

Now I am pretty sure the issue is due to having the rewrite rules I have in place, so what I suppose I am looking for is an alternative to the rewrites that still allow me to grab any newly created page url but also allows for successful error document handling.

If I have left out any vital code/information please let me know and I shall edit the post with it.

Thank you in advance for any advice/help.

EDIT::

PHP script that handles the page content.

function page_handler() {
    if(!isset($_GET['cat'])):
        $_GET['cat'] = 'generic';
        $_GET['page'] = 'home';
    endif;

    // Connect to the database
    $link = db_connect_cms();

    // Grab the id of the page
    $qry = mysqli_query($link,"
        SELECT hash,slug
        FROM cms_web_pages
        WHERE slug='".$_GET['page']."'
        AND published=1")

        or die(mysqli_error($link)
    );

    $row = mysqli_fetch_object($qry);

    // If there is a match in the db
    if(mysqli_num_rows($qry) > 0):
        $id_hash = $row->hash;
    else:
        $_GET["error"] = "404";
        require_once($_SERVER["DOCUMENT_ROOT"] . "/errors.php");
    endif;

    return array($id_hash);
}

You can achieve that by replacing this line in your PHP code:

header("location: /errors.php?error=404");

with this:

// have this code when DB lookup fails
$_GET["error"] = "404";
include($_SERVER["DOCUMENT_ROOT"] . "/errors.php");
exit; // required to prevent showing current page after error document

You cannot accieve what you are looking for only by using .htaccess.

This is how you can handle this:

  1. The RewriteRule passes the handling of the request to index.php
  2. Your application looks up the database
  3. Your application must raise the error or redirect to the error document.

It is impossible thant your .htaccess could raise the HTTP error, since the processing has been given over to the PHP script.