Leave a Reply

2 comments

  1. When a POST is set to private, non-logged in users will receive a 404 message. If you dump the global variable $wp_query,

    var_dump($wp_query);
    

    ..you will notice that no post_status is present in the parameters returned therefore using the slug (or name parameter of query_vars array for example) we can get the post status of the POST that is trying to be accessed like so,

    global $wp_query;
    $slug = $wp_query->query_vars['name'];
    $status = get_page_by_path($slug, OBJECT, 'post');
    
    if ($status->post_status == "private") {
    
         //show form
    
    } else {
    
        //etc...
    
    }
    

    Helpful Codex resources:

    http://codex.wordpress.org/Function_Reference/get_page_by_path

    Update:

    On the basis that you are trying to perform this action for the “PAGE” post type (as per your comments) the above code should change 'post' to 'page' accordingly in get_page_by_path().

    Now the reason why it still was not working while using $wp_query->query_vars['name']; is then related to the fact that your page is a CHILD page of another page, in otherwords it has a PARENT.

    Because the function we are using is getting our page by its path, it needs to know its full path so the parent page matters. Therefore we must change,

    $slug = $wp_query->query_vars['name'];
    

    to

    $slug = $wp_query->query['pagename']; //which will show the full path e.g. parent/child
    

    Elaborating further what we are doing is accessing the full path from a different array within the $wp_query and here’s an example (sample snippet) of what is $wp_query is actually comprised of when dumping the results

      ["query"]=>  //we are now accessing the ["query"] array instead of ["query_vars"]
      array(2) {
        ["page"]=>
        string(0) ""
        ["pagename"]=> //and this is what need, notice the full path
        string(20) "sample-page/sub-page"
      }
      ["query_vars"]=>
      array(57) {
        ["page"]=>
        int(0)
        ["pagename"]=> //this is what we don't need, no full path contained, will not work
        string(8) "sub-page"
        etc.......
    

    Therefore the modified code in full will look like;

    global $wp_query;
    $slug = $wp_query->query['pagename']; //from ->query_vars to ->query
    $status = get_page_by_path($slug, OBJECT, 'page'); //change to meet your desired post_type
    
    if ($status->post_status == "private") {
    
         //show form
    
    } else {
    
        //etc...
    
    }
    

    As Kaiser mentioned you can also use, get_post_status() function to retrieve the post status and that can be done like so,

    if (get_post_status($status->ID) == "private") ... etc
    
  2. Was just looking around for this answer myself in 2020 and it seems this is a great way to do it now.

    <?php if ( $wp_query->have_posts() ) : ?>
      <?php while ( $wp_query->have_posts() ) : ?>
        <?php $wp_query->the_post(); ?>
    
        <?php if ( get_post_status ( get_the_ID() ) == 'private' ) { ?>
          <h1>Private</h1>
        <?php } ?>
      <?php endwhile; ?>
    <?php endif; ?>