2

I'm trying to display a taxonomy description based on which taxonomy the page is set to display (set with a variable)

As it is, I'm only seeing the first description, regardless of which category variable is set.

Here's how I've set it up:

I've built a custom post type called 'product' and set up a taxonomy called'product_type'.

    //Register product post type
    add_action('init', 'product_register');
    function product_register() {
        $labels = array(
            'name' => ('Products'),
            'singular_name' => ('Product'),
            'add_new' => ('Add New'),
            'add_new_item' => ('Add New Product'),
            'edit_item' => ('Edit Product'),
            'new_item' => ('New Product'),
            'view_item' => ('View Product'),
            'search_items' => ('Search'),
            'not_found' => ('Nothing found'),
            'not_found_in_trash' => ('Nothing found in Trash'),
            'parent_item_colon' => ''
            );
        $args = array(
            'labels' => $labels,
            'menu_icon' => 'dashicons-tag',
            'public' => true,
            'has_archive' => true,
            'supports' => array('title', 'revisions', 'editor','thumbnail'),
            'capability_type' => 'post',
            'rewrite' => array("slug" => "product"), // Permalinks format
            );
        register_taxonomy('product_type', array('product'), array(
            'hierarchical' => true,
            'label' => 'Product Type',
            'singular_label' => 'Type',
            'show_ui' => true,
            'show_admin_column' => true,
            'query_var' => true,
            'rewrite' => true)
        );
        register_post_type( 'product' , $args );
    }

In the wordpress back end, I've loaded this with a few terms and have also added in descriptions.

Admin category list with values archive-products.php works like a landing page, but will accept information from a variable called $type to filter the content.

    if (isset($_GET['type']) || !empty($_GET['type']) ) {
        $filtered = true;
        $type = $_GET['type'];
    }

With that information, I can set up a WP_Query for items that contain that taxonomy term.

    if ($filtered == true) {
        $type = explode(' ', $_GET['type']);
        $taxonomy = array(
            array(
                'taxonomy' => 'product_type',
                'field'    => 'slug',
                'terms'    => $type
                )
            );
    $args = array(
        'post_type' => 'product',
        'posts_per_page' => -1,
        'order' => 'DEC',
        'orderby' => 'title',
        'offset' => '0',
        'tax_query' => $taxonomy
        );
    $the_query = new WP_Query($args);
    if($the_query->have_posts()):
        $terms = get_the_terms( $post->ID, 'product_type' );
    if($terms) {
        foreach( $terms as $term ) {
    echo $term->description; //always shows first term description, but should display description based on $type
    }
    }
    while($the_query->have_posts()):$the_query->the_post();
    the_title();
    the_content();
    endwhile;
    else: //nothing to show here
    endif;} else {
    // non-filtered page design
    }

The query works great but, as I mentioned earlier, it's only pulling the first taxonomy description.

This is the part that is meant to handle that:

    $terms = get_the_terms( $post->ID, 'product_type' );
    if($terms) {
        foreach( $terms as $term ) {
    echo $term->description;
    }
    }

I had guessed that it needed to be inside the query to land on the correct description, but it doesn't seem to make a difference.

I have also tried this:

    $term = get_term_by( $post->ID, $type, 'product_type' );
    echo $term->description;

but that doesn't return anything.

I'm out of ideas. I haven't found anything via google or by searching this site.

Any advice is appreciated, thanks in advance.

3
  • How many terms will you pass through $_GET['type'] Jul 21, 2015 at 17:34
  • I could pass multiple variables into it. for example: ?type=twine%20netwrap%20other $type = explode(' ', $_GET['type']); After a few more steps, it looks like this: 'terms' => array('twine','netwrap','other') Just an added level of functionality, but for the project it won't ever pass more than one unless it's done manually.
    – mdcrtv
    Jul 21, 2015 at 17:52
  • Great, thank for the reply, I'm busy with an answer ;-) Jul 21, 2015 at 17:55

1 Answer 1

1

You have a lot of issues here:

  • You should not be using $_GET variables without sanitizing it. Never ever trust any user inputs and URL parameters. They might contain malicious code which can harm your site. To sanitize and validate a $_GET variable, use the filter_input php function

    $filtered = filter_input( INPUT_GET, 'type', FILTER_SANITIZE_STRING )
    
  • Use the main query and use pre_get_posts to filter the main query accordingly. There is no need to use a custom query as this is an archive page

  • You are trying to get the current term description wrong, you should be using get_term_by to get the term object which will hold the info you need

  • This might be unrelated, but why aren't you using a taxonomy.php page which will handle all the above as it should. You just need to flush your permalinks and everything should work as it should. But this is something you need to look into in your own time

Lets first sort out the archive page. I have commented the code in order to make it easy to understand. I don't know how many terms you will pass, but from your code I have taken more that 1. If not, please see the code and adjust accordingly

$filtered = filter_input( INPUT_GET, 'type', FILTER_SANITIZE_STRING );
if ( $filtered  ) {
    /**
     * I don't know if you will be passing more than one term. From your code it seems so
     */
    $types = explode( ' ', $filtered ); 
    foreach ( $types as $type ) {

        /**
         * Get the term object. 
         *
         * I have used the slug here as it seems that you are passing the slug. Adjust as necessary
         *
         * @see get_term_by()
         */
        $term = get_term_by( 'slug', $type, 'product_type' );
        // Make sure that $term has a valid value before outputting anything
        if ( !empty( $term ) || !is_wp_error( $term ) )
            echo $term->description; // Show term description
    }
    /* Replace code above with the following if you are passing just one term
    $term = get_term_by( 'slug', $filtered, 'product_type' ); 
    if ( !empty( $term ) || !is_wp_error( $term ) )
        echo $term->description; // Show term description
    */
    if ( have_posts() ) {
        while( have_posts() ) {
            the_post();

            the_title();
            the_content();
        }
    }

} else {

    // non-filtered page design
    // I don't know what will be displayed here, so I'm keeping the loop and this separate

}

This should sort the archive page. By default, the following is passed by default, so we will not pass them in our action

  • post type

  • offset.

So, lets look at our action. I have again commented the code to make it easy to follow. Please note, the following requires at least PHP 5.4+ due to the short array syntax ([]) being used. For older versions, roll back to old array syntax (array())

add_action( 'pre_get_posts', function ( $q ) 
{
    $filtered = filter_input( INPUT_GET, 'type', FILTER_SANITIZE_STRING );
    if (    !is_admin() // Only target the front end
         && $q->is_main_query() // Only target the main query
         && $q->is_post_type_archive( 'product' ) // Only target product archive page
         && $filtered // If we have a $_GET['type'] variable
    ) {
        if ( isset( $q->get( 'tax_query' ) ) ) //Get current tax query
            $tax_query = []; // Set current tax_query to an empty array

        // Set our new tax_query
        $tax_query = [
            [
                'taxonomy'         => 'product_type',
                'field'            => 'slug'
                'terms'            => explode( ' ', $filtered ),
                'include_children' => false
            ]
        ];
        $q->set( 'tax_query', $tax_query ); // Set new tax_query
        $q->set( 'posts_per_page', -1 ); // Get all posts
        $q->set( 'order', 'DESC' ); // Descending sort order
        $q->set( 'orderby', 'title' ); // Sort by title
    }
});

I hope this is what you need

2
  • Very informative, thank you. I'll adjust my code and will let you know if I have any issues. Oh, and the reason I used a url variable instead of taxonomy.php was so I could (if necessary) pass multiple variables into a filtered page. Perhaps that's possible to do with taxonomy.php, but I'm not very familiar with it. Anyway, thanks again.
    – mdcrtv
    Jul 21, 2015 at 19:02
  • No problem. You can adjust a taxonomy page as well, but with this multi term filtering it does not really matter :-) Jul 21, 2015 at 19:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.