WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

What I am looking to do is check if a page is private, give the users the option to register and see the page. Here is what I have now:

if (have_posts()) :
    /* Print the most as normal */
else : 
  if ($post->post_status = 'private')
    /* Print login/register box */
    /* Print page not found message */
endif; ?>

My problem is that it is always falling through and displaying the login box even when the page does not exists. How do I fix this?

share|improve this question
Can we see the full code of your loop, please? Also: this is in the context of a static page, right? – Chip Bennett Jan 5 '13 at 15:54
up vote 5 down vote accepted

When a POST is set to private, non-logged in users will receive a 404 message. If you dump the global variable $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 {



Helpful Codex resources:



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'];


$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) {
    string(0) ""
    ["pagename"]=> //and this is what need, notice the full path
    string(20) "sample-page/sub-page"
  array(57) {
    ["pagename"]=> //this is what we don't need, no full path contained, will not work
    string(8) "sub-page"

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 {



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
share|improve this answer
I got this working, except I am using the Custom Permalinks plugin. I'm pretty sure this is messing it up, because this does not work on the pages that I used the plugin to change the permalink. Is there a way to look this up by ID instead of slug? Thanks! – hornj Jan 5 '13 at 17:43
If you know the ID ahead of time then yes, which you could pass along in your query_vars or what would be simpler is to see what already exists within your query_vars for us to use (hence which is what the above method is doing). So if you can do, var_dump($wp_query); so we can see what is held in the global variable $wp_query for that page users are landing on (then copy your output to pastebin.com) so I can inspect the results so we get this working for you. Also when you say "pages" do you mean "page" or "post" because they are two different post types and the... (cont) – userabuser Jan 6 '13 at 3:37
...example shown using get_page_by_path() is set to the 'post' post_type. You'd need to change that to 'page' if you are working with a 'page' post_type and so on. Once we know more about your permalink structure (that's been created under the conditions/influence of that plugin) we'll be able to ascertain what specifically we can use to help you. – userabuser Jan 6 '13 at 3:40
They are indeed pages versus posts, and I did change it from your example code. In looking at it more it doesn't seem to be interaction with the plugin, but whether it is a top level page. Here is the var_dump from this page. It doesn't work, but this does and here is it's var_dump. Thanks for your help! – hornj Jan 7 '13 at 13:16
My php code is here – hornj Jan 7 '13 at 13:23

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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