0

I am creating a WordPress custom widget and I created the below one that is working fine when I add it in function.php.

<?php
/* ------------------------------------------------------------------------- *
 *  Most Commented Post Widget
/* ------------------------------------------------------------------------- */
class show_popular_commented extends WP_Widget {

function show_popular_commented() {
 $widget_ops = array('classname' => 'show_popular_commented', 'description' => __('Show your popular commented posts.'));
 $this->WP_Widget('show_popular_commented', __('EXE_Widgets - Popular Commented Posts'), $widget_ops);
 }

function widget($args, $instance){
 extract($args);
 $title = $instance['title'];
 $postscount = $instance['posts'];
//Show The Most Commented Posts
 global $postcount;
 $myposts = get_posts(array('orderby' => 'comment_count','numberposts' =>$postscount));
 echo $before_widget . $before_title . $title . $after_title; //Widget Data
 echo '
 <style type="text/css">
 .commented_post {display:block;margin:10px 0;border-bottom:1px solid #DEDEDE;}
 .commented_post h4{font-size:16px;clear:both;display:block;}
 .commented_post p{font-size:13px;text-align:justify;line-height:18px;margin:10px 0;}
 </style>
 ';
 foreach($myposts as $post){
 setup_postdata($post);
 echo '<div class="commented_post">';
 echo '<h4><a href="';
 echo the_permalink();
 echo '">';
 echo the_title();
 echo'</a></h4>';
 echo the_excerpt();
 echo '</div>';
 }
 echo $after_widget;  //Widget Data
//Show The Most Commented Posts
 }


function update($newInstance, $oldInstance){
 $instance = $oldInstance;
 $instance['title'] = strip_tags($newInstance['title']);
 $instance['posts'] = $newInstance['posts'];
 return $instance;
 }

function form($instance){
 if(empty($instance['title'])){ $instance['title'] = '';}{
 echo '<p><label  for="'.$this->get_field_id('title').'">' . __('Title:') . ' </label><input style="width:100%;" id="'.$this->get_field_id('title').'"  name="'.$this->get_field_name('title').'" type="text"  value="'.$instance['title'].'" /></p>';
 }
 if(empty($instance['posts'])){ $instance['posts'] = '';}{
 echo '<p><label  for="'.$this->get_field_id('posts').'">' . __('Number of Posts:',  'widgets') . ' </label><input style="width:50px;" id="'.$this->get_field_id('posts').'"  name="'.$this->get_field_name('posts').'" type="text"  value="'.$instance['posts'].'" /></p>';
 }
 echo '<input type="hidden" id="custom_recent" name="custom_recent" value="1" />';
 }

 }

add_action('widgets_init', create_function('', 'return register_widget("show_popular_commented");'));
?>

Now the problem is that I don't want to use too many echo''; as I used in the above code...

 echo '<div class="commented_post">';
 echo '<h4><a href="';
 echo the_permalink();
 echo '">';
 echo the_title();
 echo'</a></h4>';
 echo the_excerpt();
 echo '</div>';

But when I use one echo''; and code the above one like below then my widget is not working properly. It is getting all variables data but not the HTML tags that I wrote in echo'';...

 echo '<div class="commented_post"><h4><a href="'.the_permalink().'">'.the_title().'</a></h4>'.the_excerpt().'</div>';

Can you answer me why it is not accepting single echo'';?

2
  • Look at the Widget API. You should never use extract() and most of all never use create_function() Commented Dec 11, 2014 at 14:11
  • @PieterGoosen Can you suggest me good alternative or can edit the code? In other way, below answer is now working fine... Commented Dec 11, 2014 at 14:49

2 Answers 2

1

Technically your first example is also incorrect, but the problem is not apparent. You're using template tags that themselves echo their content. For example, you can write simply:

the_permalink();

without echo, and the permalink will be output. This is because that function echoes its value. To output the permalink within an echo or variable assignment you need to use get_permalink:

echo get_permalink()

Just about all WordPress template tags have equivalent get_ versions, or an argument that toggles echo and return, like the_title:

the_title( '', '', false );

Here the 3rd parameter toggles echo (true) or return (false).

1
  • Thanks for your answer. From your answer, Now I am using the mentioned echo''; and its working fine. Mine new is echo '<div class="commented_post"><h4><a href="'.get_permalink().'">'.the_title( '', '', false ).'</a></h4><p>'.get_the_excerpt().'</p></div>';... Commented Dec 11, 2014 at 14:46
1

This should just be an extension to the answer by @Milo

There are a couple of flaws in your code

  • You should not be using extract(). It is hard to debug and causes unexpected output. All instances of extract() was removed from core

  • PHP 5.2 is dead, and for that matter 5.3 aswell. create_function() is pre 5.3. This is one big security risk as it uses eval() which should be avoided at all cost. The correct way is just to use function()

  • Rather use WP_Query in place of get_posts(). WP_Query results get cached making it faster

  • Class name words should start with camelcase

  • Make proper use of opening and closing php tag to avoid the overwhelming use of echo

I have rewritten your complete widget to align it with the current Widget API. You can just make the tweaks you want to add or remove

/* ------------------------------------------------------------------------- *
 *  Most Commented Post Widget
/* ------------------------------------------------------------------------- */
class Show_Popular_Commented extends WP_Widget {

    public function __construct() {
        parent::__construct(
            'show_popular_commented', 
            __( 'Popular Commented Posts' ), 
            array( 'description' => __( 'Show your popular commented posts.' ), 
            ) 
        );
        $this->alt_option_name = 'show_popular_commented';

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

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

        if ( ! is_array( $cache ) ) {
            $cache = array();
        }

        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'] : __( 'Commented 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;
        }

        /**
         * Filter the arguments for the Commented Posts widget.
         *
         * @since 1.0.0
         *
         * @see WP_Query::get_posts()
         *
         * @param array $args An array of arguments used to retrieve the commented posts.
         */
        $query_args = [
            'posts_per_page'    => $number,
            'orderby'           => 'comment_count',
        ];
        $q = new WP_Query( apply_filters( 'comment_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(); ?>

                <div class="commented_post">
                    <style type="text/css">
                        .commented_post {display:block;margin:10px 0;border-bottom:1px solid #DEDEDE;}
                        .commented_post h4{font-size:16px;clear:both;display:block;}
                        .commented_post p{font-size:13px;text-align:justify;line-height:18px;margin:10px 0;}
                    </style>

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

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

                </div><!-- #post-## -->

                <?php
            }


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

        if ( ! $this->is_preview() ) {
            $cache[ $args['widget_id'] ] = ob_get_flush();
            wp_cache_set( 'widget_commented_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'];
        $this->flush_widget_cache();

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

        return $instance;
    }

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

    public function form( $instance ) {

        $title      = isset( $instance['title'] ) ? esc_attr( $instance['title'] ) : '';
        $number     = isset( $instance['number'] ) ? absint( $instance['number'] ) : 5;
        ?>

        <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>

    <?php
    }

}

add_action( 'widgets_init', function () {
    register_widget( 'Show_Popular_Commented' );
});
1
  • My pleasure. I hope it helps. Enjoy :-) Commented Dec 15, 2014 at 4:31

Your Answer

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

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