WordPress.org

Ready to get started?Download WordPress

Forums

[resolved] Custom Taxonomy Template (Help Me Understand the Array) (21 posts)

  1. AMEEKER
    Member
    Posted 5 months ago #

    I have a custom post type (totd) and a custom taxonomy (totd_cat) that has a custom rewrite (small-business-tips/category) with four terms (social, marketing, technology, operations). On the CPT template, the single CPT template, and the taxonomy templates, there is a menu to choose the terms of the taxonomy in order those posts. For the taxonomy template, I have taxonomy-totd_cat.php which has in it the code below, which current produces http://m.angiemeekerdesigns.com/small-business-tips/category/marketing/ (for example, that is one of the terms in the taxonomy). It is drawing from all of the posts in the post type, rather than just the term of the taxonomy chosen. I don't understand how to get the template to show only the posts of the taxonomy term chosen. Also, I know the array is wrong, but I don't know how to fix it. My custom post type template works perfectly using practically the same code, but without the is_tax array.

    /** Replace the standard loop with our custom loop */
    remove_action( 'genesis_loop', 'genesis_do_loop' );
    add_action( 'genesis_loop', 'totd_do_cat_loop');
    add_action( 'genesis_loop', 'totd_teasers_do_cat_loop');
    
    add_action('pre_get_posts', 'myprefix_query_offset', 1 );
    function myprefix_query_offset(&$query) {
    
        //First, define your desired offset...
        $offset = $query->get('offset');
    
        //Next, determine how many posts per page you want (we'll use WordPress's settings)
        $ppp = 10;
    
        //Next, detect and handle pagination...
        if ( $query->is_paged ) {
    
            //Manually determine page query offset (offset + current page (minus one) x posts per page)
            $page_offset = $offset + ( ($query->query_vars['paged']-1) * $ppp );
    
            //Apply adjust page offset
            $query->set('offset', $page_offset );
    
        }
        else {
    
            //This is the first page. Just use the offset...
            $query->set('offset',$offset);
    
        }
    }
    
    add_filter('found_posts', 'myprefix_adjust_offset_pagination', 1, 2 );
    function myprefix_adjust_offset_pagination($found_posts, $query) {
    
        //Define our offset again...
        $offset = $query->get('offset');
    
            //Reduce WordPress's found_posts count by the offset...
            return $found_posts - $offset;
        }
    
    add_action('genesis_loop', 'totd_do_cat_loop');
    function totd_do_cat_loop() {
    if ( !is_paged() ) {
    	global $wp_query;
    	// Set up your query here
    	$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
    	$query = array(
    		'post_type' => 'tipoftheday',
    		'orderby'        => 'date',
    		'posts_per_page' => '1',
    		'tax_query' => array(
            array(
                'taxonomy' => 'totd_cat',
                'field' => 'slug',
                'terms' => array ('social', 'marketing', 'operations', 'technology')
            ))
    
    	);
    
    	$wp_query = new WP_Query( $query );
    
    	if( $wp_query->have_posts() ):
    		while( $wp_query->have_posts() ): $wp_query->the_post();
    			// Get the custom fields
    			        // Store the pre tips data
            $tips_data_pre = array(
                    'totd_tags' => get_field( 'totd_tags' ),
                    'tip_article_headline' => get_field( 'tip_article_headline' ),
                    'article_author' => get_field( 'article_author' ),
                    'article_author_link' => get_field( 'article_author_link' ),
            );
    
    // Only output if we have tips data
            if ($tips_data_pre['totd_tags'] != '' ||
                    $tips_data_pre['tip_article_headline'] != '' ||
                    $tips_data_pre['article_author'] != '' ||
                    $tips_data_pre['article_author_link'] != '') {
                   echo '<span class="date time published" title="%1$s">' , do_shortcode('[post_date]'),'</span>' ;
    
                    echo '<div class="tip-excerpt"><p><div class="entry-content">';
                   echo '<div class=h1 entry-title"><a href="'.get_permalink().'"title="'.get_the_title().'">' . get_the_title() . '</a></div>';
    						   echo the_excerpt();
                                    echo '<div class="entry-terms">' , do_shortcode('[post_terms taxonomy="totd_tags" before="See More Tips For: " taxonomy="totd_tags"] '),'</div>' ;
                                    echo '<div class="entry-terms">
                                                                                    <div class="share">Share This Tip:</div>
                                                                                            <div class="addthis_toolbox addthis_default_style">
                                                                                                    <a class="addthis_button_preferred_1"></a>
                                                                                                    <a class="addthis_button_preferred_2"></a>
                                                                                                    <a class="addthis_button_preferred_3"></a>
                                                                                                    <a class="addthis_button_preferred_4"></a>
                                                                                                    <a class="addthis_button_compact"></a>
                                                                                                    <a class="addthis_counter addthis_bubble_style"></a>
                                                                                            </div>
                                                                                            <script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=manta"></script>
                                                                                    </div>
                                                                    </div></div>';
    
                    echo '</p>';
            }
    
    		endwhile;
    
    	endif;
    	// Reset the query
    	wp_reset_query();
    	}
    }
    
    add_action('genesis_loop', 'totd_teasers_do_cat_loop');
    function totd_teasers_do_cat_loop() {
    	global $wp_query;
    	// Set up your query here
    	$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 0;
    	$query = array(
    		'post_type' => 'tipoftheday',
    		'orderby'        => 'date',
    		'posts_per_page' => '10',
    		'offset'		=> '1',
    		'paged'  => $paged,
    	);
    
    	$wp_query = new WP_Query( $query );
    
    	if( $wp_query->have_posts() ):
    		while( $wp_query->have_posts() ): $wp_query->the_post();
    
    			// Get the custom fields
    			        // Store the pre tips data
            $tips_data_pre = array(
                    'totd_tags' => get_field( 'totd_tags' ),
                    'tip_article_headline' => get_field( 'tip_article_headline' ),
                    'article_author' => get_field( 'article_author' ),
                    'article_author_link' => get_field( 'article_author_link' ),
            );
    
    // Only output if we have tips data
            if ($tips_data_pre['totd_tags'] != '' ||
                    $tips_data_pre['tip_article_headline'] != '' ||
                    $tips_data_pre['article_author'] != '' ||
                    $tips_data_pre['article_author_link'] != '') {
    				echo '<div class="time-teaser">
    				<span class="day">',get_the_time( 'l' ),'</span>
    				<span class="month">',get_the_time( 'm/d/Y' ),'</span> </div>';
    
                    echo '<div class="tip-excerpt"><p><div class="entry-content">';
    echo '<div class=h2 entry-title"><a href="'.get_permalink().'"title="'.get_the_title().'">' . get_the_title() . '</a></div>';
                    $excerpt = get_the_excerpt();
      echo string_limit_words($excerpt,25); echo '<a class="moretag" href="'. get_permalink($post->ID) . '"> Continue Reading→</a>';
                                    echo '<div class="entry-terms">' , do_shortcode('[post_terms taxonomy="totd_tags" before="See More Tips For: " taxonomy="totd_tags"] '),'</div>' ;
                                    echo '<div class="entry-terms"></div>
                                                                    </div></div>';
    
                    echo '</p>';
            }
    
    		endwhile;
    		// Pagination! Woo!
    		genesis_posts_nav();
    	endif;
    	// Reset the query
    	wp_reset_query();
    }
    
    genesis();

    The part above that I think is most specific to what I'm looking at is

    if ( !is_paged() ) {
    	global $wp_query;
    	// Set up your query here
    	$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
    	$query = array(
    		'post_type' => 'tipoftheday',
    		'orderby'        => 'date',
    		'posts_per_page' => '1',
    		'tax_query' => array(
            array(
                'taxonomy' => 'totd_cat',
                'field' => 'slug',
                'terms' => array ('social', 'marketing', 'operations', 'technology')
            ))
    
    	);
  2. Chip Bennett
    Theme Review Admin
    Posted 5 months ago #

    A couple questions:

    1. This is the taxonomy-totd_cat.php template file?
    2. If so, are your pre_get_posts and posts_found callbacks working? That would be extremely unusual, since by the time the template is loaded, those actions/filters are long-past

    Also, there is a lot of code here, most of which is probably not relevant to the question. Can you pare it down to the key sections of code, just for ease of clarity/legibility?

  3. AMEEKER
    Member
    Posted 5 months ago #

    Yes, that's the taxonomy-totd_cat.php template.

    And yes, the pre_get_posts and posts_found work. For example, the terms - if I were to just leave one term in the array in the first loop, and then leave a different term in an is_tax array in the second loop, I could test that the template is still working as I need it to (or another example, take out the is_tax arrays all together and put in different post types for both loops).

    But, I can't figure how to get the same template to show just the posts from the one term chosen.

  4. Chip Bennett
    Theme Review Admin
    Posted 5 months ago #

    Okay, let's back up just a bit. I want to make sure I'm understanding what you're wanting to do, and where it's failing. Because that seems to be an awful lot of query manipulation for what's actually getting rendered.

    It looks like you just want taxonomy-totd_cat.php to be used to display the taxonomy term archive index? If so, you shouldn't need any of the query manipulation you're doing.

    What happens if you just output a loop, with all of the various query manipulations removed?

  5. Christian1012
    Member
    Posted 5 months ago #

    'terms' => array ('social', 'marketing', 'operations', 'technology')

    This line is requesting all the posts tagged with any of the above. So they would all be in the WP_Query object. What Chip is saying is if you were to just use the main query object, you should have the corrects posts in the object, (ie, just the ones you want).

  6. Chip Bennett
    Theme Review Admin
    Posted 5 months ago #

    What @Christian1012 said. That's the TL;DR.

    I was going to get there, but I'm trying to do so in a way that helps you understand what's happening with the query and template manipulations. :)

  7. AMEEKER
    Member
    Posted 5 months ago #

    I do, but the first post displays differently than the rest (not just styling, but different structure for the content) than the next 10 (hence the offset in pre_get_posts and found_posts - also to keep the pagination correct) and the two loops.

    If I go with a straight loop, won't I lose all of that?

  8. AMEEKER
    Member
    Posted 5 months ago #

    Well, replacing it all with just straight loops seems to work, but I lose the # of posts and offsets for the first loop and second. If I can get that back (1 post for first loop, 10 for second with the second loop offset 1 post) while keeping the pagination (which at this point works), I guess I'm good to go.

  9. AMEEKER
    Member
    Posted 5 months ago #

    Sweet. Thanks guys. That did it. Added the posts per and the offset and I'm good to go.

    Ugh. Why did that seem so hard!

  10. Christian1012
    Member
    Posted 5 months ago #

    Why are you using two loops?

  11. Christian1012
    Member
    Posted 5 months ago #

    Good to hear it's fixed. You can ignore my curiosity above if you like.

  12. AMEEKER
    Member
    Posted 5 months ago #

    No you can see -
    http://m.angiemeekerdesigns.com/small-business-tips/

    The first post has different structure than the following 10.

  13. Christian1012
    Member
    Posted 5 months ago #

    Just a suggestion:

    The way you have it coded above, you iterate over the object twice. Once for the first loop, and then again for the second. To cut down on resources, load times, and actual coding time, you may want to use a counter. Then you only have to iterate over the loop once.

    if ( have_posts() ) :
        // Set a counter
        $count = 0;
        while ( have_posts () ) : the_post();
            // Increment the counter
            $count++;
            // If not paged and it's the very first post
            if( !$paged && $count = 1 ) {
                // Do special stuff for first post.
            }
            else {
                // Do regular stuff for all other posts.
            }
        endwhile;
    endif;
  14. Chip Bennett
    Theme Review Admin
    Posted 5 months ago #

    So, the *right* way to do that in your template file would be:

    1) A *custom* loop for the first post
    2) Callbacks for pre_get_posts and found_posts, moved to functions.php

    By *custom* loop, I mean something like:

    $latest_totd = new WP_Query( /* args here */ );
    if ( $latest_totd->have_posts() ) : while ( $latest_totd->have_posts() ) : $latest_totd->the_post();
        // Custom, first-post loop markup here
    endwhile; endif;
    // IMPORTANT
    wp_reset_postdata();

    Then, just output your normal loop:

    if ( have_posts() ) : while ( have_posts() ) : the_post();
        // Normal loop markup here
    endwhile; endif;

    That's all you need for your template file. The rest goes in functions.php.

    Your pre_get_posts callback:

    function totd_pre_get_posts( $query ) {
        // target the main query on the totd_cat tax template
        if ( $query->is_tax( 'totd_cat' ) && $query->is_main_query() ) {
            // apply offset here
            // Use your current code
        }
    }
    add_action( 'pre_get_posts', 'totd_pre_get_posts' );

    Then, your found_posts filter:

    function totd_found_posts( $found_posts, $query ) {
        // Same query conditionals
        if ( $query->is_tax( 'totd_cat' ) && $query->is_main_query() ) {
            // Put your found_posts callback stuff here
        }
    }
    add_filter( 'found_posts', 'totd_found_posts', 10, 2 );

    And you should be good to go.

  15. Christian1012
    Member
    Posted 5 months ago #

    Yes indeed, what Chip said above. Although he suggests using two loops as you did. I guess to each his own. But I absolutely agree on moving pre_get_posts and found_posts to functions.php.

  16. Chip Bennett
    Theme Review Admin
    Posted 5 months ago #

    I neglected to mention: if the first-post special markup is only intended for the latest post, and only display on the first page of the taxonomy archive index, you should wrap it in an is_paged() conditional:

    if ( ! is_paged() ) {
        $latest_totd = new WP_Query( /* args here */ );
        if ( $latest_totd->have_posts() ) : while ( $latest_totd->have_posts() ) : $latest_totd->the_post();
            // Custom, first-post loop markup here
        endwhile; endif;
        // IMPORTANT
        wp_reset_postdata();
    }

    And I do think that two queries are appropriate here. We're literally pulling the latest post out of the normal query, and treating it in a special way.

  17. AMEEKER
    Member
    Posted 5 months ago #

    *headdesk*

  18. Chip Bennett
    Theme Review Admin
    Posted 5 months ago #

    *headdesk*

    I feel your pain. :)

    Okay, what's happening here: WordPress executes in a specific order, based on a series of actions, that fall roughly in this order:

    1. Initialize WordPress (init, etc.)
    2. Read the URL query parameters (parse_request)
    3. Parse the URL query parameters, and build the database query (parse_query)
    4. Run the database query, and fetch the posts that match the parameters (pre_get_posts, posts_selection, posts_found)
    5. Determine which template file to use to output the posts (template_include)
    6. Redirect to that template (template_redirect)

    From that point, the template takes over (the stuff in your template file is executed).

    So, as you can see, pre_get_posts and posts_found happen *well before* your template code gets executed. By the time the code in your template is executed, you're past the opportunity to modify the main query properly.

    So, if you want to modify the main query properly - i.e. at pre_get_posts, you have to tell WordPress about your callback before the action fires. (Likewise with the posts_found filter.)

    The functions.php file executes at plugins_loaded, which happens before the abridged list above. That's why it's suitable for adding callbacks for pre_get_posts and posts_found.

    WordPress will then use your callbacks, and adjust the query accordingly, before it ever runs the query. That way, pagination and all the normal loop things just work out-of-the-box, auto-magically.

    Then, when you get in the template file, WordPress already knows how to handle the query - if it didn't, it wouldn't have selected that particular template file. At that point, you just want to let WordPress do its thing; if you attempt further manipulation of the query at that point, you'll just confuse things, and stomp on your already carefully-crafted query.

  19. Christian1012
    Member
    Posted 5 months ago #

    And I do think that two queries are appropriate here. We're literally pulling the latest post out of the normal query, and treating it in a special way.

    "Latest" post is different than "first" post. The "latest" post is literally the first post ordered by date descending. If the main query was later modified ( which is obviously a popular choice in @AMEEKER's case) to display in a random order, then the "first" post, would not be random, it would still be the "latest post".

    I don't mean to argumentative, I just don't see why two queries would be necessary for applying a different style/structure to the first post. I'm sure you wouldn't recommend using 5 queries if she wanted to structure and style every other post differently. Or every third.

    @AMEEKER : We've all been there.

  20. Chip Bennett
    Theme Review Admin
    Posted 5 months ago #

    There are indeed many ways to skin a cat. That's the beauty and power of knowing how to do query manipulations properly in the first place: it makes it much easier to manipulate it exactly the way you need/want to.

    If the intent is just to make the very first-output post styled differently? There's CSS for that, and ways in the query object to output a custom class for just the first post, via the post_class filter.

    (I must have missed the part about the post order being random; my mistake. :) )

  21. Christian1012
    Member
    Posted 5 months ago #

    Oh indeed, many ways. For clarity's sake, the random post order was just a hypothetical for the intellectual conversation.

    If the intent is just to make the very first-output post styled differently? There's CSS for that, and ways in the query object to output a custom class for just the first post, via the post_class filter.

    Good suggestion on using CSS, but what if you wanted the "first" post of the query to display the_content and all other posts to display the_excerpt. That's not just styling, that's actual output. I agree though, you have to know exactly what you want in order to figure out the best and easiest way to query the database.

Reply

You must log in to post.

About this Topic