Custom taxonomy archive page problem

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 term red, 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 new name__in parameter in a new WP_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 be description) and you are still going to write your special posts as in EDIT 1 with the title as explained

  • What 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 the WP_Query class. Here is the code. You can also link to the answer from @birgire. This goes into your functions.php

    class 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