0

Can you please tell me how can I create a wordpress posts widget that outputs posts based on a categories selection ( category checkboxes of all the post categories )

This is in my form function:

<?php
foreach ( get_categories() as $category ) : ?>

    <p>
    <input class="checkbox" type="checkbox" id="" name="" />
    <label for=""><?php echo $category->name ?></label>
    </p>    

<?php endforeach; ?>

For now I just opted for adding categories slug in a text field and use that with 'category_name' argument in WP_Query

I just can't wrap my head around it. Thanks for any help.

  • Well, I figured out how to do it in the end. I'm not really sure if it's the cleanest way ( there aren't that many lines of code though ) but it works just fine. If someone is interested in seing how I did it or wants to help me make the code cleaner, please do tell. Anyway, I'll also take a closer look at it tomorrow. – Silviu Andrei Mar 16 '15 at 17:20
  • Once you can, please post your solution as an answer to this question and accept it if it's the best one. – mrwweb Mar 16 '15 at 18:13
  • 2
    Welcome to WPSE. To get you started on this site and all SE sites for that matter, feel free to take a tour and also visit help center to learn how these sites operates. :-) – Pieter Goosen Mar 16 '15 at 18:14
2

I have recently written a widget that

  • Gets all the terms from the build in taxonomy category and adds them in dropdown in the widget

  • Stores the selected category and uses that category in a custom WP_Query to get and display posts from the selected category

You can look through it and adjust as needed: (Required PHP 5.4+)

(EDIT: Thanks @birgire for spotting the use of array() and [] notation. Corrected to use only [])

<?php
/**
 * Category_Posts widget class
 *
 * Displays posts from a selected category
 *
 * @since 1.0.0
*/
class Category_Posts extends WP_Widget 
{

    public function __construct() 
    {
        parent::__construct(
            'widget_category_posts', 
            _x( 'Category Posts Widget', 'Category Posts Widget' ), 
            [ 'description' => __( 'Display a list of posts from a selected category.' ) ] 
        );
        $this->alt_option_name = 'widget_category_posts';

        add_action( 'save_post', [$this, 'flush_widget_cache'] );
        add_action( 'deleted_post', [$this, 'flush_widget_cache'] );
        add_action( 'switch_theme', [$this, 'flush_widget_cache'] );
    }

    public function widget( $args, $instance ) 
    {
        $cache = [];
        if ( ! $this->is_preview() ) {
            $cache = wp_cache_get( 'widget_cat_posts', 'widget' );
        }

        if ( ! is_array( $cache ) ) {
            $cache = [];
        }

        if ( ! isset( $args['widget_id'] ) ) {
            $args['widget_id'] = $this->id;
        }

        if ( isset( $cache[ $args['widget_id'] ] ) ) {
            echo $cache[ $args['widget_id'] ];
            return;
        }

        ob_start();

        $title          = ( ! empty( $instance['title'] ) ) ? $instance['title'] : __( 'Category Posts' );
        /** This filter is documented in wp-includes/default-widgets.php */
        $title          = apply_filters( 'widget_title', $title, $instance, $this->id_base );
        $number         = ( ! empty( $instance['number'] ) ) ? absint( $instance['number'] ) : 5;
        if ( ! $number ) {
            $number = 5;
        }
        $cat_id         = $instance['cat_id'];
        $random         = $instance['rand'] ? true : false; 
        $excerpt        = $instance['excerpt'] ? true : false; 
        $thumbnail      = $instance['thumbnail'] ? true : false; 

        /**
         * Filter the arguments for the Category Posts widget.
         *
         * @since 1.0.0
         *
         * @see WP_Query::get_posts()
         *
         * @param array $args An array of arguments used to retrieve the category posts.
         */
        if( true === $random ) {

            $query_args = [
                'posts_per_page'    => $number,
                'cat'               => $cat_id,
                'orderby'           => 'rand'
            ];

        }else{  

            $query_args = [
                'posts_per_page'    => $number,
                'cat'               => $cat_id,
            ];

        }
        $q = new WP_Query( apply_filters( 'category_posts_args', $query_args ) );

        if( $q->have_posts() ) {

            echo $args['before_widget'];
            if ( $title ) {
                echo $args['before_title'] . $title . $args['after_title'];
            }               

            while( $q->have_posts() ) {
                $q->the_post(); ?>

                <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>> 

                    <header class="entry-header">
                        <?php the_title( '<h1 class="entry-title"><a href="' . esc_url( get_permalink() ) . '" rel="bookmark">', '</a></h1>' ); ?>
                    </header><!-- .entry-header -->

                    <?php 
                    if ( has_post_thumbnail() && true === $thumbnail ) { ?>

                        <div class="post-thumbnail">

                            <?php the_post_thumbnail(); ?>

                        </div><!--/.post-thumbnail-->

                    <?php   
                    }

                    if( true === $excerpt ) { ?>    

                        <div class="entry-summary">
                            <?php the_excerpt(); ?>
                        </div><!-- .entry-summary -->

                    <?php } ?>

                </article><!-- #post-## -->

                <?php
            }


            wp_reset_postdata();
        }
            echo $args['after_widget']; 

        if ( ! $this->is_preview() ) {
            $cache[ $args['widget_id'] ] = ob_get_flush();
            wp_cache_set( 'widget_cat_posts', $cache, 'widget' );
        } else {
            ob_end_flush();
        }
    }

    public function update( $new_instance, $old_instance ) 
    {
        $instance                   = $old_instance;
        $instance['title']          = strip_tags( $new_instance['title'] );
        $instance['number']         = (int) $new_instance['number'];
        $instance['cat_id']         = (int) $new_instance['cat_id'];
        $instance['rand']           = $new_instance['rand'];
        $instance['excerpt']        = $new_instance['excerpt'];
        $instance['thumbnail']      = $new_instance['thumbnail'];
        $this->flush_widget_cache();

        $alloptions = wp_cache_get( 'alloptions', 'options' );
        if ( isset($alloptions['widget_category_posts']) )
            delete_option('widget_category_posts');

        return $instance;
    }

    public function flush_widget_cache() 
    {
        wp_cache_delete('widget_cat_posts', 'widget');
    }

    public function form( $instance ) 
    {

        $title      = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
        $number     = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
        $cat_id     = isset( $instance['cat_id'] ) ? absint( $instance['cat_id'] ) : 1;
        $random     = isset( $instance['rand'] ) ? $instance['rand'] : false; 
        $excerpt    = isset( $instance['excerpt'] ) ? $instance['excerpt'] : false; 
        $thumbnail  = isset( $instance['thumbnail'] ) ? $instance['thumbnail'] : false; 
        ?>

        <p>
            <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
            <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo $title; ?>" />
        </p>

        <p>
            <label for="<?php echo $this->get_field_id( 'number' ); ?>"><?php _e( 'Number of posts to show:' ); ?></label>
            <input id="<?php echo $this->get_field_id( 'number' ); ?>" name="<?php echo $this->get_field_name( 'number' ); ?>" type="text" value="<?php echo $number; ?>" size="3" />
        </p>

        <p>
            <label for="<?php echo $this->get_field_id('cat_id'); ?>"><?php _e( 'Category Name:' )?></label>
            <select id="<?php echo $this->get_field_id('cat_id'); ?>" name="<?php echo $this->get_field_name('cat_id'); ?>">
                <?php 
                $this->categories = get_categories();
                foreach ( $this->categories as $cat ) {
                    $selected = ( $cat->term_id == esc_attr( $cat_id ) ) ? ' selected = "selected" ' : '';
                    $option = '<option '.$selected .'value="' . $cat->term_id;
                    $option = $option .'">';
                    $option = $option .$cat->name;
                    $option = $option .'</option>';
                    echo $option;
                }
                ?>
            </select>
        </p>

        <p>
            <label for="<?php echo $this->get_field_id('rand'); ?>"><?php _e( 'Show random posts' ); ?></label>
            <?php $checked = ( $random ) ? ' checked=\"checked\" ' : ''; ?>
            <input type="checkbox" id="<?php echo $this->get_field_id( 'rand' ); ?>" name="<?php echo $this->get_field_name( 'rand' ); ?>" value="true" <?php echo $checked; ?> />    
        </p>

        <p>
            <label for="<?php echo $this->get_field_id('excerpt'); ?>"><?php _e( 'Show excerpt. If unchecked, only the title of the post will be displayed' ); ?></label>
            <?php $checked = ( $excerpt ) ? ' checked=\"checked\" ' : ''; ?>
            <input type="checkbox" id="<?php echo $this->get_field_id( 'excerpt' ); ?>" name="<?php echo $this->get_field_name( 'excerpt' ); ?>" value="true" <?php echo $checked; ?> />    
        </p>

        <p>
            <label for="<?php echo $this->get_field_id('thumbnail'); ?>"><?php _e( 'Hide post thumbnail' ); ?></label>
            <?php $checked = ( $thumbnail ) ? ' checked=\"checked\" ' : ''; ?>
            <input type="checkbox" id="<?php echo $this->get_field_id( 'thumbnail' ); ?>" name="<?php echo $this->get_field_name( 'thumbnail' ); ?>" value="true" <?php echo $checked; ?> />    
        </p>

    <?php
    }

}

add_action( 'widgets_init', function () 
{
    register_widget( 'Category_Posts' );
});
  • nice to see the object caching, I guess part of it is already cached via WP_Query ps: just a minor thing: I spotted both the array() and [] notation – birgire Mar 17 '15 at 11:23
  • Thanks for your sharp eyes. Copy and paste error between an older widget. Crap. Need to go through all those and rectify. Hate mixing of syntax, lol. – Pieter Goosen Mar 17 '15 at 11:28
  • it's usually easier noticing stuff like that when doing code reviews for others, than oneself ;-) – birgire Mar 17 '15 at 11:35
  • ps: ignore the after widget stuff I wrote ;-) – birgire Mar 17 '15 at 11:41
  • Hahaha, ok. Posting from my phone, so I can only see updates to comments and posts once I refresh browser. Only see now you have removed that part :-) – Pieter Goosen Mar 17 '15 at 11:48

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.