34

Is there a way to show a 404 page if the current logged in user does not have the right clearance to view the page? I am looking for a PHP method, something like

if( !current_user_can('administrator') ) { show_404(); exit(); }

I have thought about using a redirect, but I would like to keep the url the same.

2
  • If you are denying access to a user for a page which exists, 404 is the wrong error code to use. A 401 or 403 would make more sense.
    – moopet
    Commented Jul 12, 2013 at 9:18
  • 1
    You are right. I was under the impression from the client that he did not want anyone without access to even know the page existed, throwing a 401 would say it exists but prohibited. Nonetheless, it would be an easy change to throw a 401 instead.
    – Evan Yeung
    Commented Jul 12, 2013 at 19:11

4 Answers 4

79

I was able to display a 404 error by using the following code in my header.

<?php
  global $wp_query;
  $wp_query->set_404();
  status_header( 404 );
  get_template_part( 404 ); exit();
?>

To break it down:
$wp_query->set_404(): tells the wp_query this is a 404, this changes the title
status_header(): sends a HTTP 404 header
get_template_part(): displays the 404 template

1
  • This is a good answer, but I would also use http_status_code(404); prior to setting the template to insure that the header is correct (which is significantly faster than the wordpress status_header( 404 ); function). If you are concerned with page rank, you should also put a Disallow rule in your robots.txt to indicate that it is not a public resource.
    – mopsyd
    Commented Mar 15, 2018 at 2:12
3

Why don't you create a page that show error message and then redirect user to that page? Here is a simple way to achieve that:

Open the 404.php file and add these lines to the top of it:

/**
 * Template Name: 404 Page
 */

Create a page with 404 Page template. Then redirect users:

if ( !current_user_can('administrator') ) {
    $404_page = get_permalink( $404_page_id );
    wp_redirect( $404_page );
    exit();
}

The reason you should use a page for 404 request is: in WP 404 page actually is a page that doesn't exists, WP has to search for all of its content before returning the 404 page and that work is a waste of resource. Using a pre-configured page that might help you run your blog faster.

3
  • I have thought about using this. But a couple downfalls that I see is that two 404 templates would have to be created and maintained (page and real). The client would have to create a 404 page. And I would like to keep the URL the same. Example, if I go to example.com/restricted, I would not be redirected to .../404/
    – Evan Yeung
    Commented Aug 4, 2011 at 7:02
  • Actually I just realized that the 404.php is the template. My mistake.
    – Evan Yeung
    Commented Aug 4, 2011 at 7:24
  • 2
    No, that is a pretty terrible idea if you like having any kind of page ranking. Search engines only consider pages that return a 404 or any 4xx range header as viewer error, and will happily index anything that returns a 200 page. If you do a redirect, then you are telling crawlers that your not found page is a valid page, and it will mess up your page ranking badly. All you really need to do when you get a 404 page is do http_response_code(404); exit();. If you want a page, then use get_template_part( 404 ); before exit. That is also much faster than any wordpress functionality.
    – mopsyd
    Commented Mar 15, 2018 at 2:05
3

I had a similar requirement where I should not let users access the author.php page based on the role a user was in. I register the template_redirect action to do my checks and redirect to 404 page even before the actual page is loaded.

Registration:

add_action( 'template_redirect', [ $this, 'handle_inactive_users']);

Handler:

public function handle_inactive_users() {
    global $wp_query;
    if ( $wp_query->is_author() ) {
        $user = $wp_query->get_queried_object();
        if ( is_a( $user, \WP_User::class ) && $user->has_cap( 'inactive' ) ) {
            $wp_query->set_404();
            status_header( 404 );
            get_template_part( 404 );
            exit();
        }
    }
}

If you chose to only use the following code snippet in the middle of template part, the page may have already been rendered partially and you are not actually redirected to a 404 page. So better to do it in the template_redirect action -

$wp_query->set_404();
status_header( 404 );
get_template_part( 404 );
exit();
0

You can write this code to file 404.php in actually used theme directory (wp-content/themes/..../404.php):

<?php
header("HTTP/1.1 301 Moved Permanently");
header("Location: ".get_bloginfo('url'));
exit();
?>

This code must start from begin of file (without any characters before).

Link to original: How to Redirect your 404 page to the Home Page in WordPress

2
  • The OP is actually looking for a way to have 404 displayed for users that don't meet a certain criteria, e.g. "If user A doesn't have the 'can_edit' capability, then display a 404 page."
    – phatskat
    Commented Jun 5, 2017 at 15:18
  • Do not redirect 404s. Location: xxx sets a 301 header, which tells crawlers that there is actually a valid resource, and kills your ranking when they determine that there isn't.
    – mopsyd
    Commented Mar 15, 2018 at 2:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.