WordPress.org

Ready to get started?Download WordPress

Forums

[resolved] Get custom taxonomy terms to be displayed in relative categories? (10 posts)

  1. Kevin
    Member
    Posted 2 months ago #

    Hi everybody,

    Sorry it was really hard to think of a good topic title that would describe what I am going for. So here is the story...

    I have set up a taxonomy filter for my client that displays results on the search template. Here is the main part of the code that relates to this question:

    <!-- Search Results Container -->
    <div id="search-container">
    	<?php /* Start the Loop */ ?>
    	<?php if( have_posts() ) : while ( have_posts() ) : the_post(); ?>
    		<?php // Retrieve Custom Taxonomy Values for Each Attorney.  I.e. their location, position, etc.
    			//$location = wp_get_object_terms( $post->ID, 'locations');
    			//$bar_admissions = wp_get_object_terms( $post->ID, 'bar-admissions');   <-- UNCOMMENT THESE IF YOU WOULD LIKE TO INTEGRATE THEM INTO THE SEARCH RESULTS.  YOU WILL ALSO HAVE TO EDIT THE SINGLE ATTORNEY SECTION AS SEEN BELOW
    			//$languages = wp_get_object_terms( $post->ID, 'languages');
    			//$practice_areas = wp_get_object_terms( $post->ID, 'practice-areas');
    			//$schools = wp_get_object_terms( $post->ID, 'schools');
    			$link = get_permalink();
    			$position = wp_get_object_terms( $post->ID, 'positions');
    			$position = $position[0]->name;
    			$phone = get_field( 'phone_number' );
    			$email = get_field( 'email' );
    			$vcard = get_field( 'vcard' );
    		?>
    
    		<!-- Single Attorney Entry -->
    		<div id="attorney-entry">
    			<span><a href="<?php echo $link; ?>"><strong><?php the_title(); ?></strong></a></span>
    			<span>P: <?php echo $phone; ?></span>
    			<span>E: <a href="mailto:<?php echo $email; ?>"><?php echo $email; ?></a></span>
    			<span><a href="<?php echo $vcard; ?>" download><img src="<?php echo site_url( '/wp-content/themes/rodenolaw/images/vcard_download.png' ); ?>" width="48" height="48" alt="vCard"></a><span>
    			<span class="position"><?php echo $position; ?></span>
    		</div>
    		<!-- /end single attorney entry -->
    
    	<?php endwhile; else: ?>
    	<!-- Message if no attorneys are found -->
    	<p>Sorry, no attorneys matched your criteria. Please go back to our <a href="our-attorneys">attorney directory</a> and try again.</p>
    	<?php endif; ?>
    </div>
    <!-- /end search results container -->

    So I have this configured to display the results in alphabetical order according to custom taxonomy called last-name. Everything is working fine up to this point.

    So what my client would like is for the the results page to look something like this: http://www.brunini.com/attorneys-search.html. As you can see, the results are organized and displayed in seperate categories according to the first letter of their last name.

    What I already have set up is a custom taxonomy called last-name-latter. What I am looking to do is have the search results page check to see which terms for last-name-letter are showing up from the queried posts (the terms would be A, B, C etc.), then display alphabetical headings for the terms used as well as list the attorneys with the same terms underneath their corresponding headings. It would be easier to understand if you just visit the example site I mentioned.

    I am thinking I will have to set up individual divs for every single letter, then use a conditional to display them only if their term shows up in one or more of the queried post. I will have to think through this more, but just seeing if any of you can come up with a clean solution to this.

    Thanks ahead of time.

  2. Kevin
    Member
    Posted 2 months ago #

    Ok getting closer. Here is what I have so far. The following code will fetch all terms for last-name-letter, then arrange organize the posts belonging to that taxonomy and display them underneath their relevant term. The only thing is that I can easily do this for all of the posts of my post-type. However, I would like to limit it it so just the search results.

    <?php //start by fetching the terms for the last name letter taxonomy
    $terms = get_terms( 'last-name-letter', array(
    	'order'    => 'ASC',
    	'hide_empty' => 0
    ) );
    // now run a query for each last name letter
    foreach( $terms as $term ) {
    
    	// Define the query
    	$args = array(
    		'last-name-letter' => $term->slug
    	);
    	$query = new WP_Query( $args );
    	//outbut the first letter of last name and list attorneys belonging to that taxonomy
    	echo'<h2>' . $term->name . '</h2>';
    	echo '<ul>';
    		// Start the Loop
    		while ( $query->have_posts() ) : $query->the_post(); ?>
    
    			<!-- Single Attorney Entry -->
    			<div id="attorney-entry">
    				<span><a href="<?php echo $link; ?>"><strong><?php the_title(); ?></strong></a></span>
    				<span>P: <?php echo $phone; ?></span>
    				<span>E: <a href="mailto:<?php echo $email; ?>"><?php echo $email; ?></a></span>
    				<span><a href="<?php echo $vcard; ?>" download><img src="<?php echo site_url( '/wp-content/themes/rodenolaw/images/vcard_download.png' ); ?>" width="48" height="48" alt="vCard"></a><span>
    				<span class="position"><?php echo $position; ?></span>
    			</div>
    			<!-- /end single attorney entry -->
    
    		<?php endwhile;
    
    	echo '</ul>';
    
    	//Reset postdata
    	wp_reset_postdata();
    
    } ?>
  3. Kevin
    Member
    Posted 2 months ago #

    Got it. Here is the final code for anybody that might be looking for a similar solution. Sorry about all of the comments I'm trying to help out the developer who I will be handing this to.

    <!-- Search Results Container -->
    <div id="search-container">
    	<?php 	$post_ids = array();
    			foreach ($posts as $post) {
    				$post_ids[] = $post->ID;
    			};
    			$args = array( 'order' => 'ASC' );
    			$terms = wp_get_object_terms( $post_ids, 'last-name-letter', $args );
    
    			// Run a query for each last name letter being used
    			foreach( $terms as $term ) {
    				$args = array(
    					'last-name-letter' => $term->slug
    				);
    				$query = new WP_Query( $args );
    				//Display the first letter of last name and list attorneys belonging to that taxonomy
    				echo'<h2>' . $term->name . '</h2>';
    				echo '<ul>';
    
    					/* ---------------------------------------------------------------*/
    					/*    THIS IS THE CONTENT FOR EACH INDIVIDUAL ATTORNEY DISPLAY	  */
    					/* ---------------------------------------------------------------*/
    
    						// Start the Loop
    						while ( $query->have_posts() ) : $query->the_post();
    
    						// Retrieve Custom Taxonomy Values for Each Attorney.  I.e. their location, position, etc.
    							//$location = wp_get_object_terms( $post->ID, 'locations');
    							//$bar_admissions = wp_get_object_terms( $post->ID, 'bar-admissions');   <-- UNCOMMENT THESE IF YOU WOULD LIKE TO INTEGRATE THEM INTO THE SEARCH RESULTS.  YOU WILL ALSO HAVE TO EDIT THE SINGLE ATTORNEY SECTION AS SEEN BELOW
    							//$languages = wp_get_object_terms( $post->ID, 'languages');
    							//$practice_areas = wp_get_object_terms( $post->ID, 'practice-areas');
    							//$schools = wp_get_object_terms( $post->ID, 'schools');
    							$link = get_permalink();
    							$position = wp_get_object_terms( $post->ID, 'positions');
    							$position = $position[0]->name;
    							$phone = get_field( 'phone_number' );
    							$email = get_field( 'email' );
    							$vcard = get_field( 'vcard' );
    		?>
    							<!-- Single Attorney Entry -->
    							<div id="attorney-entry">
    								<span><a href="<?php echo $link; ?>"><strong><?php the_title(); ?></strong></a></span>
    								<span>P: <?php echo $phone; ?></span>
    								<span>E: <a href="mailto:<?php echo $email; ?>"><?php echo $email; ?></a></span>
    								<span><a href="<?php echo $vcard; ?>" download><img src="<?php echo site_url( '/wp-content/themes/rodenolaw/images/vcard_download.png' ); ?>" width="48" height="48" alt="vCard"></a><span>
    								<span class="position"><?php echo $position; ?></span>
    							</div>
    							<!-- /end single attorney entry -->
    
    						<?php endwhile;
    
    					/* ------------------ END OF ATTORNEY DISPLAY  ------------------*/
    					/* ---------------------------------------------------------------*/
    
    				echo '</ul>';
    
    				//Reset postdata
    				wp_reset_postdata();
    			} ?>
    </div>
    <!-- /end search results container -->
  4. Kevin
    Member
    Posted 2 months ago #

    Sorry, this thread seems to be a one-way conversation and you are seeing my struggles throughout the day. Just saw that the code above isn't exactly perfect. The terms are going under their proper headings, but they are not display in alphabetical order. I have tried all sorts of solutions to this and can't find one. Hopefully someone migh thave an easy fix.

  5. bcworkz
    Member
    Posted 2 months ago #

    Hi there, having fun are we? ;)

    I think you're over thinking this, as a result you are running potentially 27 queries when one will do. We should strive to minimize queries, they tax the server.

    I suggest you go back and start with the alphabetical listing that works off the single search query. Inside the Loop, add a conditional that checks the first letter of the last name (or the assigned letter term if you prefer) before the current post is output. When a change of letter (or term) is detected, close out any previous divs or p's or whatever if required (but not if the first post), then output a heading for the new letter and open any required divs, p's, etc. as needed.

    The loop then proceeds as usual. The script will need to keep track of the current first letter or term in order to detect when it changes. The variable storing this should be initialized to something impossible, such as punctuation, before the loop starts so that on the first post a "change" is detected, causing the output of the first heading.

    After the Loop completes, if there are any open divs, p's, etc., close them out.

    Still not very elegant, but it's fairly straight forward without needless complications.

  6. Kevin
    Member
    Posted 2 months ago #

    Hey BC, if I had seen this before the project's deadline maybe I would have tried to implement it. How would you have checked to see if the next post in the loop had a different "letter term" than the previous?

  7. bcworkz
    Member
    Posted 2 months ago #

    Before the loop initiate the variable for keeping track of the current letter by setting it to a never used letter:
    $current_letter = 'ǻ';

    Then in the loop, do something like this:

    $initial = strtoupper( substr( get_field('last_name'), 0, 1));
    // could have gotten letter term above instead of extracting 1st initial
    
    // if names have a new initial...
    if ( $initial != $current_letter ) {
       if ( 'ǻ' != $current_letter )
          {// except for first instance, output any closing tags opened for previous initial group}
       echo "<h2 class='really_big_initial'>$initial</h2>";
       // output container divs, p's, etc. as needed for each initial group
       $current_letter = $initial;
    }
    // output the usual loop content

    After the loop ends output any closing tags opened for final initial group.

  8. Kevin
    Member
    Posted 2 months ago #

    Ahh the strtoupper function would have come in handy. Like you said this seems to be a much cleaner solution without the extra queries. So basically this would require the initial query and loop. Then during the loop it would be returning all of the posts in alphabetical order according to the last names (configured elsewhere), but because of the $current_letter = $initial at the end of each post the next one in the loop can determine whether or not they are the same, and if not return a new heading.

    This is pretty simple and smooth IMO, why would you say it's not? Do you think the code I posted is going to have a major impact on performance? Most likely the initial query would only fetch a few initials, not all 27.

  9. bcworkz
    Member
    Posted 2 months ago #

    Yeah, I suppose you're right, it is simple and smooth. When I previously said it wasn't elegant, I think I envisioned something more clunky being required without thinking too much of the details. As so often happens in PHP for me, the final implementation ends up being much simpler than I had initially imagined. PHP has a very rich set of powerful functions that I'm not used to having as a resource.

    For modest sized databases, I doubt there would be a noticeable difference. For large databases there could be a pronounced difference. It's always a good idea to write code that scales well without the need for major rewrites.

  10. Kevin
    Member
    Posted 2 months ago #

    Right I agree. Again, had I seen this before I definitely would have used it. I just don't have access to the files now, so there I don't have an easy way of changing it. Again, the database should not be too large relatively speaking. I will contact the client to see if he would want to go through the trouble, but because it is not a large operation I don't think we'll do it. I will definitely keep this is mind though, a lot of helpful hints here.

    Thanks again BC.

Reply

You must log in to post.

About this Topic