How to use a custom post type archive as front page in WordPress?

I’d like to use a custom post type archive as a site’s front page, so that

 http://the_site.com/

is a custom post type archive displayed according to my archive-{post-type}.php file.

Read More

Ideally I would like to alter the query using is_front_page() in my functions.php file. I tried the following, with a page called “Home” as my front page:

 add_filter('pre_get_posts', 'my_get_posts');
 function my_get_posts($query){
     global $wp_the_query;
     if(is_front_page()&&$wp_the_query===$query){
        $query->set('post_type','album');
        $query->set('posts_per_page',-1);
     }
     return $query;
 }

but the front page is returning the content of “Home” and seems to be ignoring the custom query.

What am I doing wrong? Is there a better way, in general, of going about this?

Note: I did post this in WordPress Answers but that community is comparatively tiny.

Related posts

Leave a Reply

4 comments

  1. Posting the final solution as an answer (Isaac placed it as a comment) just for anyone still looking.

    Isaac was on the right track with adding a filter via functions.php. What he did wrong was call is_front_page(), which doesn’t work yet because we’re in pre_get_posts and the query hasn’t been executed yet.

    We do have the current page ID however. So we can still solve this, by looking into the WordPress option register for an option called page_on_front, which returns the ID of the page the user set as frontpage.

    (For an overview of all WordPress options, just visit <yourwordpressinstallation>/wp-admin/options.php in your browser.)

    Which makes for the following solution as suggested by Ijaas:

    add_action("pre_get_posts", "custom_front_page");
    function custom_front_page($wp_query) {
        // Compare queried page ID to front page ID.
        if(!is_admin() && $wp_query->get("page_id") == get_option("page_on_front")) {
    
            // Set custom parameters (values based on Isaacs question).
            $wp_query->set("post_type", "album");
            $wp_query->set("posts_per_page", -1);
    
            // WP_Query shouldn't actually fetch the page in our case.
            $wp_query->set("page_id", "");
    
        }
    }
    

    You might have to alter a few conditional tags to make sure all plugins still work, depending on how heavily the query gets altered.

    Hope this helps someone.

    Update: as noted below, add !is_admin() to the if-statement to make sure the function only runs on the frontend. If you only want this action to run for the initial query, you could also add the main query check $wp_query->is_main_query().

  2. In response to Robberts solution:

    answered May 6 ’13 at 12:04

    adding && !isAdmin() to the if function other wise it replaces the post type query for all admin pages as well.
    Just in case anyone has issues with this.

    edit:
    also adding && $wp_query->is_main_query() to the if statement stops it affecting widgets and the menu

    so total code I have

    if($wp_query->get("page_id") == get_option("page_on_front") && !isAdmin() && $wp_query->is_main_query()) {}

  3. In order to get that query to work, you’re going to have to add that code to a page template, create a page, set your template as the template for the page you just created, and then set that page as the home page in Settings => Reading in the admin area.

    By the way, the is_front_page() function only returns true if you’re on a page that’s been set as the home page from the admin menu.

    The other option would be to modify index.php, but if you did that, is_front_page() would always return false. In that case, you’d want to use is_home() instead.

    I hope that helps.

  4. Isaac, you are correct, I didn’t thoroughly read your question and I made the assumption that you were looking to do this the “easy” way.

    Anyway, I put your code on my test site and, indeed, it didn’t work. I looked at my SQL log and it turns out that your code produces this in the query wp_posts.post_status = 'private'.

    So, I tried adding the line $query->set('post_status', 'public'); to your function, and it worked just fine.

    In summary, try this:

    add_filter('pre_get_posts', 'my_get_posts');
    function my_get_posts($query){
        global $wp_the_query;
        if(is_front_page()&&$wp_the_query===$query){
            $query->set('post_type','album');
            $query->set('posts_per_page',-1);
            $query->set('post_status', 'public');
        }
        return $query;
    }