# Most Discussed Posts Widget

> Adds a "Most Discussed Posts" widget that lists the posts with the most comments, all-time or from the last few weeks, with optional comment counts.

- Type: PHP
- Runs: Run everywhere
- Category: [Widgets](https://wpide.com/library/category/widgets/)
- Tags: widgets, popular-posts, comments
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/most-discussed-posts-widget/

## Code

```php
if ( ! class_exists( 'WPIDE_Most_Discussed_Widget' ) ) {
    class WPIDE_Most_Discussed_Widget extends WP_Widget {
        public function __construct() {
            parent::__construct( 'wpide_most_discussed', 'Most Discussed Posts', array(
                'description'                 => 'Posts with the most comments, optionally from recent weeks only.',
                'customize_selective_refresh' => true,
            ) );
        }

        public function widget( $args, $instance ) {
            $number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : 5;
            $days   = isset( $instance['days'] ) ? absint( $instance['days'] ) : 0;
            $key    = 'wpide_discussed_' . $number . '_' . $days;
            $ids    = get_transient( $key );

            if ( ! is_array( $ids ) ) {
                $query = array(
                    'post_type'           => 'post',
                    'posts_per_page'      => $number,
                    'orderby'             => array( 'comment_count' => 'DESC', 'date' => 'DESC' ),
                    'has_password'        => false,
                    'ignore_sticky_posts' => true,
                    'no_found_rows'       => true,
                    'fields'              => 'ids',
                );

                if ( $days ) {
                    $query['date_query'] = array( array( 'after' => $days . ' days ago' ) );
                }

                $ids = get_posts( $query );
                set_transient( $key, $ids, HOUR_IN_SECONDS );
            }

            if ( ! $ids ) {
                return;
            }

            _prime_post_caches( $ids, false, false );

            $title = isset( $instance['title'] ) && '' !== $instance['title'] ? $instance['title'] : 'Most Discussed';
            $title = apply_filters( 'widget_title', $title, $instance, $this->id_base );

            echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput -- theme markup.

            if ( '' !== (string) $title ) {
                echo $args['before_title'] . esc_html( $title ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput
            }

            echo '<ol class="wpide-most-discussed">';

            foreach ( $ids as $id ) {
                $count = (int) get_comments_number( $id );

                echo '<li><a href="' . esc_url( get_permalink( $id ) ) . '">' . esc_html( get_the_title( $id ) ) . '</a>';

                if ( ! empty( $instance['show_count'] ) ) {
                    echo ' <small>(' . esc_html( sprintf( _n( '%s comment', '%s comments', $count ), number_format_i18n( $count ) ) ) . ')</small>';
                }

                echo '</li>';
            }

            echo '</ol>';
            echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput
        }

        public function form( $instance ) {
            $title  = isset( $instance['title'] ) ? $instance['title'] : '';
            $number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : 5;
            $days   = isset( $instance['days'] ) ? absint( $instance['days'] ) : 0;

            echo '<p><label for="' . esc_attr( $this->get_field_id( 'title' ) ) . '">Title:</label><input class="widefat" type="text" id="' . esc_attr( $this->get_field_id( 'title' ) ) . '" name="' . esc_attr( $this->get_field_name( 'title' ) ) . '" value="' . esc_attr( $title ) . '" /></p>';
            echo '<p><label for="' . esc_attr( $this->get_field_id( 'number' ) ) . '">Number of posts:</label> <input class="tiny-text" type="number" min="1" max="20" id="' . esc_attr( $this->get_field_id( 'number' ) ) . '" name="' . esc_attr( $this->get_field_name( 'number' ) ) . '" value="' . esc_attr( $number ) . '" /></p>';
            echo '<p><label for="' . esc_attr( $this->get_field_id( 'days' ) ) . '">Only posts from the last (days, 0 = all time):</label> <input class="tiny-text" type="number" min="0" max="3650" id="' . esc_attr( $this->get_field_id( 'days' ) ) . '" name="' . esc_attr( $this->get_field_name( 'days' ) ) . '" value="' . esc_attr( $days ) . '" /></p>';
            echo '<p><input type="checkbox" class="checkbox" id="' . esc_attr( $this->get_field_id( 'show_count' ) ) . '" name="' . esc_attr( $this->get_field_name( 'show_count' ) ) . '"' . checked( ! empty( $instance['show_count'] ), true, false ) . ' /> <label for="' . esc_attr( $this->get_field_id( 'show_count' ) ) . '">Show comment counts</label></p>';

            return '';
        }

        public function update( $new_instance, $old_instance ) {
            return array(
                'title'      => isset( $new_instance['title'] ) ? sanitize_text_field( $new_instance['title'] ) : '',
                'number'     => isset( $new_instance['number'] ) ? max( 1, min( 20, absint( $new_instance['number'] ) ) ) : 5,
                'days'       => isset( $new_instance['days'] ) ? min( 3650, absint( $new_instance['days'] ) ) : 0,
                'show_count' => ! empty( $new_instance['show_count'] ),
            );
        }
    }
}

add_action( 'widgets_init', function () {
    register_widget( 'WPIDE_Most_Discussed_Widget' );
} );
```

## Notes

Add it under Appearance > Widgets (as a Legacy Widget in the block editor); results are cached for an hour.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Most Discussed Posts Widget" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
