再写“最近评论”widget

好多“最近评论”的widget了,有外国人写的,还有咱们自己的小糖糖维护的中文工具箱,我自已也写了替换wordpress默认的widgets,干嘛还说,因为我觉得原来的截断太复杂,我就是不喜欢那个utf8_trim的function,时不时的出点这样那样的问题,相当困扰。

其实mysql自带的截断那是相当的好用,让我隆重介绍LEFT(str,len),简单安全,老幼咸宜,咳咳,广告时间结束,我们看实例:

SELECT 
    concat(comment_author,''),
    comment_author_url,
    comment_ID,
    comment_post_ID,
    CONCAT(
        @ex:=LEFT(comment_content,30),
        IF(LENGTH(comment_content)=LENGTH(@ex),'','...')
    ) AS comment,
FROM wp_comments
WHERE comment_approved = '1' 
ORDER BY comment_date_gmt DESC 
LIMIT 10

SQL略有小复杂,容我慢慢讲,前5行没有花头,就这样。从CONCAT开始首先用LEFT(str,len)截取了留言的前30个字。然后我想给截取过的留言加三个点,所以用IF(expr1,expr2,expr3)比较截取的部分和原留言是不是一样长,因为留言原本就只有20个字(小于30)那么截取后的留言也是20个字,长度就相等。最后用CONCAT(str1,str2,...)把两部分连接起来,大功告成 ❗

缺点:在MYSQL4.1.0以前的版本对unicode支持不好,这个query一样能跑,但是,得到的汉字长度=截取长度/3,所以截取长度要设为想要的汉字长度的3倍(谁还用那么老版本的mysql,汗,我的一个服务器就是4.0.27版本)。如果你的服务器是4.1.0以后版本,包括4.1.0,恭喜你,你将完全得到你想要的结果。

上代码了:

function yixia_widget_recent_comments($args){
  global $wpdb, $comments, $comment;
  extract($args, EXTR_SKIP);
  $options = get_option('widget_recent_comments');
  $title = empty($options['title']) ? __('Recent Comments') : $options['title'];
  if ( !$number = (int) $options['number'] )
    $number = 5;
  else if ( $number < 1 )
    $number = 1;
  else if ( $number > 15 )
    $number = 15;
  if ( !$length = (int) $options['length'] )
    $length = 16;
  else if ( $length < 6 )
    $length = 6;
  else if ( $length > 60 )
    $length = 60;
  if ( !$comments = wp_cache_get( 'recent_comments', 'widget' ) ) {
    $comments = $wpdb->get_results("SELECT comment_author,comment_author_url,comment_ID,comment_post_ID,CONCAT(@ex:=LEFT(comment_content,$length),IF(LENGTH(comment_content)=LENGTH(@ex),'','...')) as comment_content FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT $number");
    wp_cache_add( 'recent_comments', $comments, 'widget' );
  }
  echo $before_widget;
  echo $before_title . $title . $after_title;
  echo '<ul id="recentcomments">';
  if ( $comments ) : foreach ($comments as $comment) :
    $comment_content = strip_tags($comment->comment_content);
    $comment_content = stripslashes($comment_content);
    echo  '<li class="recentcomments">' . sprintf(__('%1$s: %2$s'), get_comment_author_link(), '<a href="'. get_permalink($comment->comment_post_ID) . '#comment-' . $comment->comment_ID . '" title="'. get_the_title($comment->comment_post_ID) .'">'.$comment_content.'</a>') . '</li>';
  endforeach; endif;
  echo '</ul>'.$after_widget; 
}
function yixia_widget_recent_comments_control() {
  $options = $newoptions = get_option('widget_recent_comments');
  if ( $_POST["recent-comments-submit"] ) {
    $newoptions['title'] = strip_tags(stripslashes($_POST["recent-comments-title"]));
    $newoptions['number'] = (int) $_POST["recent-comments-number"];
    $newoptions['length'] = (int) $_POST["recent-comments-length"];
  }
  if ( $options != $newoptions ) {
    $options = $newoptions;
    update_option('widget_recent_comments', $options);
    wp_delete_recent_comments_cache();
  }
  $title = attribute_escape($options['title']);
  if ( !$number = (int) $options['number'] )
    $number = 5;
  if ( !$length = (int) $options['length'] )
    $length = 16;
?>
      <p><label for="recent-comments-title"><?php _e('Title:'); ?> <input class="widefat" id="recent-comments-title" name="recent-comments-title" type="text" value="<?php echo $title; ?>" /></label></p>
      <p>
        <label for="recent-comments-number"><?php _e('Number of comments to show:'); ?> <input style="width: 25px; text-align: center;" id="recent-comments-number" name="recent-comments-number" type="text" value="<?php echo $number; ?>" /></label>
        <br />
        <small><?php _e('(at most 15)'); ?></small>
      </p>
      <p>
        <label for="recent-comments-number"><?php _e('Length of comments to show:'); ?> <input style="width: 25px; text-align: center;" id="recent-comments-length" name="recent-comments-length" type="text" value="<?php echo $length; ?>" /></label>
        <br />
        <small><?php _e('(6 ~ 60)'); ?></small>
      </p>
      <input type="hidden" id="recent-comments-submit" name="recent-comments-submit" value="1" />
<?php
}
function yixia_widgets_init(){
  unregister_sidebar_widget('recent-comments');
  $widget_ops = array(
    'classname' => 'widget_recent_comments', 
    'description' => __( 'The most recent comments' ) 
  );
  wp_register_sidebar_widget('recent-comments', __('Recent Comments'), 'yixia_widget_recent_comments', $widget_ops);
  wp_register_widget_control('recent-comments', __('Recent Comments'), 'yixia_widget_recent_comments_control');
}
add_action('init', 'yixia_widgets_init', 1000);

6 Responses

  1. Betty says:

    这个是在widget里面调用?如果要直接写在主题sidebar.php里,要怎么写呢?

  2. Hee says:

    找到有用的代碼了 LENGTH(comment_content) 呵呵

  3. Charles says:

    侠姐,你怎么搞到init里面去了,plugin_loaded就可以了吧

    • 轶侠 says:

      俺这个写在functions.php里面,没有做成plugin,呵呵

      • Charles says:

        一样可以hook到plugin_loaded的啊

        • 轶侠 says:

          俺看sandbox里面都写到init,wp自己也写到init的哈