Support » Theme: Customizr » Specific category posts on startpage and other categories on a page

  • ELDEMARRAS

    (@eldemarras)


    Hola, first thanks for Customizr Theme & acub, this is driving me slowly to get more deeply into WordPress taxonomies and CSS´s!
    I have a problem that i think im quite close to have the solution, but still not on the right path.

    I need to have on the Homepage:
    – slider (FIXED)
    – 3 featured pages (FIXED)
    – Posts about a specific category or tag.

    Then on a specific page the posts about a category or tag.

    Right now i have create the Blog.php on my child theme, as its said here in the forum:
    http://wordpress.org/support/topic/recent-blogs-on-a-separate-page?replies=10#post-6007407

    Also i have done
    • Dashboard > Appearance > Customize > Homepage.
    • Select “A static page” as template.
    • Select the static page for homepage and my specific page(productos) for blog page.

    I can see the page (productos) i have created with all my posts, but no posts displayed on the startpage.

    what I´m missing after one week reading this previos thread and some experimentations?

    Thank you very much in advance!
    /v

Viewing 13 replies - 1 through 13 (of 13 total)
  • rdellconsulting

    (@rdellconsulting)

    If I understand correctly, you need to have a Blank page (productos).

    Then setup a Menu item using a Category or Tag in the panel on the left. If you can’t see those panels, go to Screen Options at top and check the boxes

    ELDEMARRAS

    (@eldemarras)

    Halo rdell,
    thanks for your fast reply.
    What i need for this specific design based on the Customizr Theme is:

    – have a front page with specific posts (based on a specific category or tag)
    – on a dedicated pago of the menu all the other category/tag posts
    I have created a child theme and uploaded a blog.php file to my child theme, but not the good result.
    here is my reference:
    http://wordpress.org/support/topic/how-to-add-a-blog-template-for-customizr?replies=36
    thanks a lot!

    ElectricFeet

    (@electricfeet)

    – on a dedicated pago of the menu all the other category/tag posts

    You mean that the posts on this other page exclude the category of the posts on the front page?

    Are the posts on the front page finite in number (so you’d want to show them all) or are they regular posts that keep being posted (so you’d want to limit their number)?

    ELDEMARRAS

    (@eldemarras)

    halo EF,
    thanks a lot for the reply,
    yes i mean the page excludes a dedicated category of the posts on the front page.

    the posts on the frontpage will be more and more news about the diferent states of the project (without limit on numbre or on time)
    thanks!
    /v

    ElectricFeet

    (@electricfeet)

    Well, this one took a while, but I think I’m there.

    Including only one category on the main blog page is easy-peasy. For the other page, which excludes that category, there are two solutions:
    – Solution “A” works if you only have one other category. It is simple.
    – Solution “B” is for where you have 2 or more other categories (and is therefore more complex).

    Assumptions for the code below:
    – The category that you want to appear on the front page (excluding all others) is called “Noticias”.

    Steps to do what you want are as follows:

    To display only one category on your front blog page (for example, only the “Noticias” category):

    1. Remove the blog.php that you put in your child theme. We don’t need it to do what I describe below.

    2. Set up Customizr as follows: In Appearance > Customize > Front Page, select “Front page displays: Your latest posts”, then select the “Save and publish” button.

    3. Add the following to your child theme’s functions.php. It will restrict the posts shown on the front page to the “Noticias” category. Change the category name to match yours.

    // Display only one category on the front page's posts. Set "Front page displays: Your latest posts" in Appearance > Customize
    add_action( 'pre_get_posts', 'set_front_page_blog_list_category' );
    function set_front_page_blog_list_category($query) {
    
    	$my_cat_to_display = get_cat_ID('Noticias'); // <<<<< CHANGE THIS TO THE CATEGORY NAME TO BE DISPLAYED ON YOUR FRONT PAGE
    
    	if ( !is_admin() && $query->is_home() && $query->is_main_query() ) {
    
    		$query->set( 'cat', $my_cat_to_display ); 
    
    	}
    }

    There are then two solutions for displaying your second blog page, depending on whether
    A. You want to show only one category on it (for example, if you only have 2 categories in total), or
    B. You want to display more than one category (for example, you want to show all the categories except one):

    Solution A—you want to display only one category on your second blog page (for example, only the “Productos” category):

    A4. Go to Appearance > Menus and select your main menu:
    – Select the Categories dropdown from the box on the left of the screen (the box that contains “Pages”, “Links” and “Categories”).
    – Choose the category you want to show—for example, “Productos”—and select the “Add to menu” button.
    – Save the menu (I always forget this step!).

    You now have a menu item that links only to the “Productos” category. If you don’t like the “Category Archive” title that shows up, you can switch it off with header.archive-header { display: none; } in your Custom CSS / child theme’s stylesheet.

    Solution B—you want to display all categories except one on your second blog page. For example, you want all your product categories and service categories in a page called “Productos y Servicios”, which will exclude your “Noticias” category:
    New assumptions:
    – You’re using post names for your permalinks
    – The category that you want to exclude from the second blog page is called “Noticias”;
    – The page is where you will display the posts is called “Productos y Servicios” and its slug is “productos-y-servicios”; and
    – You want to show 8 posts per page (I added this to the code, so that you can have a different number to the number on your home page).

    B4. Create a blank page called, for example, “Productos y Servicios”, with no content. Base it on the Customizr default template. Save it and note the slug.

    Add the following to your child theme’s functions.php:

    // Alter query on second blog page. Hooks onto Customizr's actions before and after the loop. Warning: uses query_posts()
    add_action( '__before_loop' , 'alter_query_on_second_blog_page', 5 ); // before headings etc are run
    add_action( '__after_loop'  , 'alter_query_on_second_blog_page', 50 ); // 50 ==> after comments and navigation code is done 
    
    function alter_query_on_second_blog_page() {
    
    	// call the global query variable from the current instance of WP_query
    	global $wp_query;
    
    	// Are we in the __before_loop filter hook, or the __after_filter hook?
    	switch ( current_filter() ) {
    
    		case '__before_loop':
    
    			$my_extra_blog_page_slug = 'productos-y-servicios'; // <<<<< CHANGE THIS TO THE SLUG OF THE PAGE WHERE YOU WANT TO SHOW YOUR SECOND BLOG
    			$my_cat_to_exclude = get_cat_ID('Noticias');         // <<<<< CHANGE THIS TO THE CATEGORY NAME TO BE EXCLUDED FROM YOUR SECOND BLOG
    			$my_posts_per_page = '10';                           // <<<<< CHANGE THIS NUMBER TO THE NUMBER OF PAGES YOU WANT PER PAGE ON YOUR SECOND BLOG
    
    			if ( ! is_admin() && $my_extra_blog_page_slug == $wp_query->query_vars['pagename'] && is_main_query() ) {
    
    				$paged = (get_query_var('paged')) ? get_query_var('paged') : 1; 
    
    				$args = array(
    					'post_type'         => 'post',
    					'post_status'       => 'publish',
    					'posts_per_page'    => $my_posts_per_page,
    					'paged'             => $paged,
    					'cat'               => '-' . $my_cat_to_exclude
    				);
    
    				// execute the query
    				query_posts( $args );
    			}
    
    			break;
    
    		case '__after_loop':
    
    			//reset the query changes we made
    			wp_reset_query();
    
    			break;
    	}
    }

    Change the $my_extra_blog_page_slug, $my_cat_to_exclude, and $my_posts_per_page variables to match your requirements.

    Caveats
    Solution B uses query_posts(). This is generally frowned upon because it stomps all over the main query (although you can minimise the effect by resetting everything afterwards—which I do). Using query_posts() seems to be necessary in this case, because:
    – We cannot use the normally-recommended pre_get_posts action, because our second post list is on a page. According to the Codex, “pre_get_posts cannot be used to alter the query for Page requests (page templates) because is_page, is_singular, pagename and other properties (depending if pretty permalinks are used) are already set by the parse_query() method.” So because we’re on a page yet we want a list of posts, it’s hard not to stomp all over something we don’t want (a blank page), in order to give us something that we do want (a list of posts).
    – I don’t see how we can use new WP_Query(), because is not easy to interface with Customizr, whose functions use the global variable $wp_query extensively (for example, to prettify the blog list, with the tc_post_list_display() ).

    The downside to using query_posts() is that any sidebar widgets etc that think they’re on a page will now be on a post list instead and it may give strange results. Likewise some plugins may conflict. You’ll need to test it on your setup.

    Another caveat: I’m a dabbler, not a programmer.

    Comments welcome. Specifically on whether the wp_reset_query() will mess up the page in any way when it’s run unconditionally like this. Nikeo does a conditional version here, using query_vars['page_id'], but in the case of my code above, this always seems to be equal to int(0), so I cannot do this—running query_posts() eliminates all references to the page, so I cannot test for it.

    Where’s d4z_c0nf when you need him? 🙂

    Let me know if it works for you.

    Theme Author Nicolas GUILLAUME

    (@nikeo)

    Hi @eldemarras and @electricfeet,
    In ‘productos’ page, to show your blog posts excluding one category, and to skip the use of query_posts(), (which should never been used!), here’s a what you could do : (paste this code in functions.php of your theme/child)

    //setup hooks in the template_redirect action => once the main WordPress query is set
    add_action( 'template_redirect', 'hooks_setup' , 20 );
    function hooks_setup() {
        if (! is_page('productos-y-servicios') ) //<= you can also use the page ID here
            return;
        add_action( '__before_loop'     , 'set_my_query' );
        add_action( '__after_loop'      , 'set_my_query', 100 );
    }
    
    function set_my_query() {
        global $wp_query, $wp_the_query;
        switch ( current_filter() ) {
        	case '__before_loop':
        		//replace the current query by a custom query
    		    //Note : the initial query is stored in another global named $wp_the_query
    		    $wp_query = new WP_Query( array(
    		    	'post_type'         => 'post',
    				'post_status'       => 'publish',
    		       	'cat'               => '-' . get_cat_ID('Noticias')
    		    ) );
        	break;
    
        	default:
        		//back to the initial WP query stored in $wp_the_query
        		$wp_query = $wp_the_query;
        	break;
        }
    }

    This code snippet uses a global var called $wp_the_query where WordPress carrefully store the initial query.

    @see core code in wp-settings :

    /**
     * WordPress Query object
     * @global object $wp_the_query
     * @since 2.0.0
     */
    $GLOBALS['wp_the_query'] = new WP_Query();
    
    /**
     * Holds the reference to @see $wp_the_query
     * Use this global for WordPress queries
     * @global object $wp_query
     * @since 1.5.0
     */
    $GLOBALS['wp_query'] = $GLOBALS['wp_the_query'];

    Note :
    In the Customizr theme, the __before_loop and __after_loop actions are fired each time a page is loaded and allow you to alter/customize the query before rendering the post content :

    <?php do_action ('__before_loop');##hooks the heading of the list of post : archive, search... ?>
    
        <?php if ( tc__f('__is_no_results') || is_404() ) : ##no search results or 404 cases ?>
    
            <article <?php tc__f('__article_selectors') ?>>
                <?php do_action( '__loop' ); ?>
            </article>
    
        <?php endif; ?>
    
        <?php if ( have_posts() && !is_404() ) : ?>
            <?php while ( have_posts() ) : ##all other cases for single and lists: post, custom post type, page, archives, search, 404 ?>
                <?php the_post(); ?>
    
                <?php do_action ('__before_article') ?>
                    <article <?php tc__f('__article_selectors') ?>>
                        <?php do_action( '__loop' ); ?>
                    </article>
                <?php do_action ('__after_article') ?>
    
            <?php endwhile; ?>
    
        <?php endif; ##end if have posts ?>
    
    <?php do_action ('__after_loop');##hook of the comments and the posts navigation with priorities 10 and 20 ?>
    Theme Author Nicolas GUILLAUME

    (@nikeo)

    By the way, this whole query_posts() issue is well explained by @nacin (WP core developer), here :

    ElectricFeet

    (@electricfeet)

    @nikeo Yay! :-)))))

    Thanks. That’s great! I knew there had to be a better way, but went round in circles trying to find it.

    I’d seen the video, but only understood 1/2 of it—which is much better than three days ago, when I would have understood only 1/4. Now I’m getting almost 3/4 of it. Progress! 🙂

    [ Being a testing geek, and curious to understand this fully, I spotted one glitch: In the absence of a declaration for the ‘paged’ query variable, the paging seems not to work in the code above. Specifically, the get_query_var('paged') returns int(0) on the second page—it’s not been set automatically in the new query. If you add 2 of the lines back in from my code above, it works.

    (As an aside, the codex has an error on this, I think: it recommends the code $paged = (get_query_var('paged')) ? get_query_var('paged') : 1 However, I think it should more correctly be set to 0, not 1, to match the original query’s value. Someone correct me if I’m wrong. ]

    Thanks also for the heads-up on the template_redirect hook. I felt I should have been hooking to something, rather than just doing the actions, but didn’t know where to hook. Could you spare the time to explain why you chose that hook in particular?

    @eldemarras: The full code you need to use (for the unique category on the front page and the category exclusion on the second blog) is as follows (thought I’d consolidate it to make it easier to cut & paste after nikeo’s changes and my addition):

    // Display only one category on the front page's posts. Set "Front page displays: Your latest posts" in Appearance > Customize
    add_action( 'pre_get_posts', 'set_front_page_blog_list_category' );
    function set_front_page_blog_list_category($query) {
    
        if ( !is_admin() && $query->is_home() && $query->is_main_query() ) {
    
            $query->set( 'cat', get_cat_ID('Noticias') );               // <<<<< CHANGE THIS TO THE CATEGORY NAME TO BE DISPLAYED ON YOUR FRONT PAGE
    
        }
    }
    
    // Alter query on second blog page. Sets up hooks in the template_redirect action (so after the main WordPress query is set).
    // It then hooks onto Customizr's actions before and after the loop.
    add_action( 'template_redirect', 'hooks_setup' , 20 );
    function hooks_setup() {
    
        if (! is_page('productos-y-servicios') )                        // <<<<< CHANGE THIS TO THE PAGE ID, TITLE, OR SLUG OF YOUR SECOND BLOG
            return;
    
        add_action( '__before_loop'     , 'set_my_query' );
        add_action( '__after_loop'      , 'set_my_query', 100 );
    
    }
    
    function set_my_query() {
    
        global $wp_query, $wp_the_query;
    
        switch ( current_filter() ) {
    
            case '__before_loop':
    
                // Check which page of the blog we're on, so we can pass this to the new query
                $paged = (get_query_var('paged')) ? get_query_var('paged') : 0;
    
                // Replace the current query by a new custom query.
                // The initial query is still stored in another global named $wp_the_query
                $wp_query = new WP_Query( array(
                    'post_type'         => 'post',
                    'post_status'       => 'publish',
                    'paged'             => $paged,
                    'cat'               => '-' . get_cat_ID('Noticias') // <<<<< CHANGE THIS TO THE CATEGORY NAME TO BE EXCLUDED ON YOUR SECOND BLOG PAGE
                ) );
    
            break;
    
            default:
    
                // Switch back to the initial WP query stored in $wp_the_query
                $wp_query = $wp_the_query;
    
            break;
        }
    }

    This time, no caveats as it has the nikeo stamp on it 🙂

    Theme Author Nicolas GUILLAUME

    (@nikeo)

    @electricfeet

    Being a testing geek

    😀

    Thanks for your insights on the get_query_var(‘paged’) issue!

    Theme Author Nicolas GUILLAUME

    (@nikeo)

    @electricfeet : about the template_redirect hook : it’s defined in wp-includes/template-loader.php.
    I kind of like it because it is fired once the main query and conditional tags have been fully setup and before the wp_head action.
    It’s a really perfect place to setup hooks handling conditions on the query elements.

    ElectricFeet

    (@electricfeet)

    🙂

    Thanks again!

    Guys, don’t forget that WordPress has the concept of home and front pages. The home page is the blog, the front page is the landing page, which may also be a blog or it might be static content without a blog loop.

    If you’re having problems, or want more flexibility, compare is_home() with is_front_page().

    still testing…
    thank you very much for your inputs!

Viewing 13 replies - 1 through 13 (of 13 total)
  • The topic ‘Specific category posts on startpage and other categories on a page’ is closed to new replies.