Custom taxonomy archive page problem
-
29-09-2020 - |
Question
My website is built on custom post types, that I have organized with different custom taxonomies. The menu buttons are the taxonomies archive pages (red, blue, green), so that when you click on the term 'red' of the custom taxonomy 'socks' (for example) you get all the articles that correspond to red socks. Now then, the problem is I only have one page (called taxonomy-socks.php) that deals with the custom taxonomy term archive page and I would like to set a little presentation of the red socks, the blue socks, the green socks with pictures and css style... on each archive page, but I have no idea how to acheive this ! The best choice I guess would be to make the description in an article and then display each article on each custom taxonomy term archive page... But how ? This is the code of my page taxonomy-socks.php :
<div class="main-content">
<?php $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); ?>
<div id="container">
<div id="content" role="main">
<h1><?php echo $term->name; ?></h1>
<?php
if (have_posts()) : ?>
<?php while (have_posts()) : the_post();
$i++;?>
<div class="portfolio<?php if ( ($i%3) == 0 ) { echo ' last'; } elseif ( ($i%2) == 0 ) { echo ' two-last'; } elseif ( ($i%4) == 0 ) { echo ' very-large'; } ?>" data-thematique="<?php echo implode(', ', get_field('thematique')); ?>" data-activite="<?php echo implode(', ', get_field('activite')); ?>" data-niveau="<?php echo implode(', ', get_field('niveau')); ?>">
<div class="project-image"><?php the_post_thumbnail(); ?></div>
<div class="project-info">
<span class="portfolio-title"><?php the_title(); ?></span>
<span class="portfolio-act"><span class="light">NIVEAU :</span> <span class="white"><?php the_field('niveau'); ?></span></span>
<span class="portfolio-act"><span class="light">THÉMATIQUE :</span> <span class="white"><?php the_field('thematique'); ?></span></span>
<span class="portfolio-act"><span class="light">ACTIVITÉ :</span> <span class="white"><?php the_field('activite'); ?></span></span>
<span class="portfolio-act"><span class="light">Lieu : </span><span class="white"><?php echo the_field('lieu1'); ?></span></span></div><a href="<?php echo get_permalink(); ?>" class="button portfolio-button">EN SAVOIR PLUS</a>
</div>
<?php
endwhile; ?>
<?php endif; ?></div>
</div></div>
Thanks for your help... I hope it's clear enough..
Solution
There are many choices here, and it is all up to you what you want to achieve and how you want to achieve it.
My idea would be to use the templates available to avoid a lot of if else
conditional statement. The Template Hiearchy makes provision for templates for terms, taxonomy-{$taxonomy}-{$term}.php
, so you could create a tempate for each term. So for red, you can create taxonomy-socks-red.php
.
I know this is going to get quite overwhelming, but so is any other method I think
EDIT 1
Here is something else you can try. I don't have time to test this right now as we are celebrating "Nasionale Braaidag" :-)
First, register a new post type, call it something like 'descriptions'. You can leave the defaults as is so that this post type is not publicly queryable. Please see attached link to all arguments and parameters you can use
function codex_custom_init() { $args = array( 'label' => 'Descriptions' ); register_post_type( 'descriptions', $args ); } add_action( 'init', 'codex_custom_init' );
You can now write posts that will be shown on top of your loop in your
taxonomy-socks.php
. Start of with the title of the specific term. If your post is targeting the termred
, make your title something like `Red - Great color socks to wear to the Rammstein concert'Using the following code from this answer by @G.M. you can search your custom posts by the title name and return the post if it matches the name of your term. This goes into your functions.php
// require PHP 5.3+ add_action( 'posts_where', function( $where, $query ) { if ( isset( $query->query['name__in'] ) && is_array( $query->query['name__in'] ) ) { global $wpdb; $names = array_filter( array_map( function( $name ) use( $wpdb ) { $sane = sanitize_title( $name ); return ! empty( $sane ) ? $wpdb->prepare( '%s', $sane ) : NULL; }, $query->query['name__in'] ) ); if ( ! empty( $names ) ) { $where .= " AND {$wpdb->posts}.post_name IN (" . implode( ',', $names ) . ")"; } } return $where; }, PHP_INT_MAX, 2 );
You are already getting the current term name, so no need for extra code here. You are going to return
$term->name
to the newname__in
parameter in a newWP_Query
. This query will go just above your main loop$args = array( 'post_type' => 'descriptions', 'posts_per_page' => 1, 'name__in' => $term->name ); $the_query = new WP_Query( $args ); // The Loop if ( $the_query->have_posts() ) { while ( $the_query->have_posts() ) { $the_query->the_post(); //Show what you need to show } } /* Restore original Post Data */ wp_reset_postdata();
EDIT 2
OK, I have tested everything, and it seems that the code from @G.M. is not fit for this job. I have however tested with the following code I found a while ago from @birgire in one of his answers here. This is better suited for the job
So, you need to make the changes accordingly, here is how
You are still going to register your custom post type
descriptions
(and note, it cannot bedescription
) and you are still going to write your special posts as in EDIT 1 with the title as explainedWhat is going to change is how we are going to query the posts. First of all, we are going to create a new
name__like
parameter and extend theWP_Query
class. Here is the code. You can also link to the answer from @birgire. This goes into your functions.phpclass WPSE_Query extends WP_Query // thanks @birgire https://wordpress.stackexchange.com/a/136758/31545 { public function __construct( $args = array() ) { add_filter( 'posts_where', array( $this, 'posts_where' ), 10, 2 ); parent::__construct( $args ); } public function posts_where( $where, $qry ) { remove_filter( current_filter(), array( $this, __FUNCTION__ ) ); $name__like = $qry->get( 'name__like' ); if( ! empty( $name__like ) ) { $where .= " AND "; $where .= $GLOBALS['wpdb']->posts; $where .= ".post_name LIKE '"; $where .= esc_sql( like_escape( $name__like ) ); $where .= "%' "; } return $where; } }
Now we can query the posts, but we are not going to use the original
WP_Query
method, but its new extended class,WPSE_Query
. So your new custom query will look like this$args = array( 'post_type' => 'descriptions', 'posts_per_page' => 1, 'name__like' => $term->name ); $the_query = new WPSE_Query( $args ); // The Loop if ( $the_query->have_posts() ) { while ( $the_query->have_posts() ) { $the_query->the_post(); //REMEMBER TO CHANGE THIS WITH YOUR LOOP ELEMENTS LIKE the_title(); } } /* Restore original Post Data */ wp_reset_postdata();
I hope this is exactly what you are looking for