0

I'm relatively new to Wordpress, and coding in general. I am trying to edit theme-specific recent posts widget to display only posts within a certain category. Currently, the theme will display recent posts with video thumbnails in a category, but it will also include recent posts within any subcategories of that category. I do not want to display posts that appear in subcategories of that category. Can this be done? The code is below.

Widget-home-posts file to categorize:

function widget( $args, $instance ) {
    extract( $args );

    // If user have not selected any category then display none.
    if ( empty( $instance['cat'] ) ) {
        return;
    }

    // Output the theme's $before_widget wrapper.
    echo $before_widget;

        // Pull the selected category.
        $cat_id = $instance['cat'];

        // Get the category.
        $category = get_category( $cat_id );

        // Get the category archive link.
        $cat_link = get_category_link( $cat_id );

        // Posts query arguments.
        $args = array(
            'post_type'      => 'post',
            'posts_per_page' => 3
        );

        // Limit to category based on user selected tag.
        if ( ! empty( $instance['cat'] ) ) {
            $args['cat'] = $instance['cat'];
        }

        // Allow dev to filter the post arguments.
        $query = apply_filters( 'videoz_home_recent_args', $args );

        // The post query.
        $posts = new WP_Query( $query );

Recent posts widget code:

 class VideoZ_Recent_Widget extends WP_Widget {

/**
 * Sets up the widgets.
 *
 * @since 1.0.0
 */
function __construct() {

    // Set up the widget options.
    $widget_options = array(
        'classname'   => 'widget-videoz-recent posts-thumbnail-widget',
        'description' => __( 'Display recent posts with thumbnails.', 'videoz' )
    );

    // Create the widget.
    parent::__construct(
        'videoz-recent',                                   // $this->id_base
        __( '» Recent Posts Thumbnails', 'videoz' ), // $this->name
        $widget_options                                      // $this->widget_options
    );

    // Flush the transient.
    add_action( 'save_post'   , array( $this, 'flush_widget_transient' ) );
    add_action( 'deleted_post', array( $this, 'flush_widget_transient' ) );
    add_action( 'switch_theme', array( $this, 'flush_widget_transient' ) );

}

/**
 * Outputs the widget based on the arguments input through the widget controls.
 *
 * @since 1.0.0
 */
function widget( $args, $instance ) {
    extract( $args );

    // Output the theme's $before_widget wrapper.
    echo $before_widget;
if ( $instance['title'] ) {
        echo $before_title . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $after_title;
    }
    // Display the recent posts.
        if ( false === ( $recent = get_transient( 'videoz_recent_widget_' . $this->id ) ) ) {

        // Posts query arguments.
        $args = array(
            'post_type'      => 'post',
            'posts_per_page' => $instance['limit']
        );

        // The post query
        $recent = get_posts( $args );

        // Store the transient.
        set_transient( 'videoz_recent_widget_' . $this->id, $recent );

    }

    global $post;
    if ( $recent ) {
        echo '<ul>';

            foreach ( $recent as $post ) :
                setup_postdata( $post );

                echo '<li>';
                    echo '<a class="entry-thumbnail" href="' . esc_url( get_permalink( $post->ID ) ) . '" rel="bookmark">' . get_the_post_thumbnail( $post->ID, 'videoz-widget', array( 'class' => 'entry-thumb', 'alt' => esc_attr( get_the_title( $post->ID ) ) ) ) . '<span class="play-button"><i class="fa fa-play"></i></span></a>';
                    echo '<a href="' . esc_url( get_permalink( $post->ID ) ) . '" rel="bookmark">' . esc_attr( get_the_title( $post->ID ) ) . '</a>';
                    if ( $instance['show_date'] ) :
                        echo '<time class="entry-date" datetime="' . get_the_date( 'c' ) . '">' . get_the_date() . '</time>';
                    endif;
                echo '</li>';

            endforeach;

        echo '</ul>';
    }

    // Reset the query.
    wp_reset_postdata();
  • I'm trying to figure out where the category is currently defined. Is there another part to the code? Usually you would add your category arguments to the array you're sending to get_posts(), but I can't see one there (or elsewhere) – Tim Malone Jun 6 '16 at 7:51
  • I added more of the code to the original post; however, I can't find any categories defined. It looks like the array getting passed into get_posts pulls 'post'. Right now this widget allows me to add recent posts by category to the home page. If I specify categories, will this mess with the widget UI and display? – Noey Jun 6 '16 at 9:12
  • In your question you said "Currently, the theme will display recent posts with video thumbnails in a category, but it will also include recent posts within any subcategories of that category". How is that category currently determined? – Tim Malone Jun 6 '16 at 10:52
  • @TimMalone, I didn't realize there was another file used to categorize posts. I attached part of the widget-home-posts file code above that I believe does the actual categorizing of the posts. With the code there, I assume I need to limit the $args['cat'] = $instance['cat']; to exclude the specified category ID's, or am I still missing something? – Noey Jun 8 '16 at 2:21
1

You need to pass more query arguments. In this case you need:

    $args = array(
        'post_type'      => 'post',
        'posts_per_page' => $instance['limit'],
        'category__in'   => $id
    );

Where $id is the category id, not the post id.

  • If I add 'category__in' => $id, the $id's must be categories that will appear in the recent posts on the home page? Would adding 'cat' => '-12,-34,-56' ) where -12,-34,-56 are the categories accomplish the same effect (excluding certain subcategories from appearing in recent posts)? – Noey Jun 6 '16 at 10:11
  • 1
    The $id must be the "certain category" that you mention in your question. I don't know how you select that category. You could use exclude in the way you mention, but that only works if you know exactly which categories to exclude. It you change your categories later on, you will also have to change the function. – cjbj Jun 6 '16 at 10:36
  • Thanks for your help @cjbj, please see my response to Tim Malone. The function to organize the posts by categories was located in another file. I attached the part of the code to the top of my post. Do I need to edit the line that says $args['cat'] = $instance['cat']; or $cat_link = get_category_link( $cat_id );? How would this code look, or am I still missing something? – Noey Jun 8 '16 at 2:29
  • @Noey Great, you've found it =) You want to change $args['cat'] = $instance['cat']; to $args['category__in'] = $instance['cat'];. Why? Because cat gets posts from that category plus children, and category__in gets posts only from that exact category. See codex.wordpress.org/Class_Reference/… – Tim Malone Jun 8 '16 at 3:27
  • Fantastic! This is exactly what I was looking for. Appreciate your help. – Noey Jun 8 '16 at 22:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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