I know I can publicly show future posts in a loop using 'post_status' => 'future' in WP_Query. But clicking on a future post's permalink will result in a 404 if you are not a logged-in user.

Suppose I have a post called Apocalypse in the post_type 'event', scheduled for 12-12-2099. The permalink is mysite.com/event/apocalypse. Is it possible to make mysite.com/event/apocalypse and other future 'event' posts visitable now by the public?

Ideally I'd be able to restrict future post availability to the 'event' post type, but I would settle for a solution that makes all future posts available regardless of post_type.

  • why do u need a future post to be viewable to non logged in users? I think i can come up with a solution but im just checking.
    – Ijaas
    Oct 4, 2011 at 3:32

5 Answers 5


In short, you can make future posts visible by telling Wordpress to mark them as 'published' instead of 'scheduled'. You do this by using a future_post hook, which gets called when a post changes status. Each post type automatically gets its own future hook; since the custom post type I'm using is event, I can use the future_event hook. Here is the code:

function setup_future_hook() {
// Replace native future_post function with replacement

function publish_future_post_now($id) {
// Set new post's post_status to "publish" rather than "future."

add_action('init', 'setup_future_hook');

This solution came from this SE question: Marking future dated post as published

A caveat with this approach

The caveat I will add is that this makes it more difficult to get a loop of just future posts. Before, I could simply use 'post_status' => 'future'; but now, since we've set future posts' post_status to published, that doesn't work.

To get around this you can use a posts_where filter on your loop (for example, see the date range examples on the codex here: http://codex.wordpress.org/Class_Reference/WP_Query#Time_Parameters), or you can compare the current date to the post date, something like this:

    // get the event time
    $event_time = get_the_time('U', $post->ID);

    // get the current time
    $server_time = date('U');

    // if the event time is older than (less than)
    // the current time, do something
    if ( $server_time > $event_time ){
       // do something

However, neither of these techniques is as easy as having a separate post_status for future posts. Perhaps a custom post_status would be a good solution here.


I would like to give my answer all this time later. In the case of making all the 'future' posts for the 'events' post type visible to the public, I found this solution:

add_filter('get_post_status', function($post_status, $post) {
    if ($post->post_type == 'events' && $post_status == 'future') {
        return "publish";
    return $post_status;
}, 10, 2);
  • 1
    This worked fine :)
    – Sami
    Feb 24 at 9:31

For me the given snippet didn't worked, there were some errors in the post-edit.php, but I guess that $postatt is now null in 4.6.1.

Anyways that's the final solution that worked for me like a charm.

add_filter('the_posts', 'show_all_future_posts');

function show_all_future_posts($posts)
   global $wp_query, $wpdb;

   if(is_single() && $wp_query->post_count == 0)
      $posts = $wpdb->get_results($wp_query->request);

   return $posts;
  • This was the only one that worked for me too.
    – Pete
    Nov 19, 2020 at 12:48

I forced the publish status from functions.php of a child theme

global $wpdb;
$wpdb->query("update ".$wpdb->prefix."posts set post_status='publish' where post_status='future' and post_type in ('post','customposttype1','customposttype2')");

I will add my solution to this issue; which seems to be cleaner in the aspect that you can still have a future status ( and not force publish status to all your posts:

  1. we raise $wp_query_event a flag when we detect that we are on single post and it is the post type we wish to enable it. ( we break function otherwise )

  2. we keep set the $post on the WP_Query so we will have the proper $queried_object to any other future reference

  3. if the lateset queried object is of our type ( using the previous flag we raised ) and the post is of the future status, assigned it as our posts result.

The code:

$wp_query_event = false;
add_filter( 'posts_results', function( $posts, $wp_query ) {
    global $wp_query_event;
    if ( !$wp_query->is_main_query() || !$wp_query->is_single || !isset( $wp_query->query_vars[ 'event' ] ) ) return( $posts );
    $wp_query->post = $posts[ 0 ];
    $wp_query_event = true;
    return( $posts );
}, 50, 2 );

add_filter( 'the_posts', function( $posts, $wp_query ) {
    global $wp_query_event;
    if ( !$wp_query_event ) return( $posts );
    $wp_query_event = false;
    if ( !empty( $posts ) ) return( $posts );
    $post = $wp_query->get_queried_object();        
    if ( in_array( $post->post_status, [ 'future' ] ) ) {
        $posts = [ $post ];
    } else {
        $wp_query->post = null;
    return( $posts );
}, 50, 2 );

Your Answer

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

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