\"Typecho文章排行插件实现(按日排行、周排行、月排行、总排行)\"

原理很简单: 要实现文章按日期排行,你就必须记录文章每天的点击率,于是新建数据表是必须的:

CREATE TABLE IF NOT EXISTS `typecho_ranks` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `cid` int(10) NOT NULL,
  `hits` int(10) NOT NULL,
  `date` date NOT NULL,
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`)
) ENGINE=MYISAM  DEFAULT CHARSET=%charset%;

然后就是Plugin文件了,这只是我今天写的原始版,可能还并不是很规范,测试后我会发布该插件:

<?php
/**
 * 实现文章日排行、周排行、月排行、年排行、总排行
 * @package RankPlugin
 * @author Mckee
 * @version 1.0
 * @  http://www.phpddt.com
 */
class ArticleRank_Plugin implements Typecho_Plugin_Interface
{
    /**
     * 激活插件方法,如果激活失败,直接抛出异常
     * 
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function activate()
    {
        $info = ArticleRank_Plugin::installTable();
        Typecho_Plugin::factory(\'Widget_Archive\')->beforeRender = array(\'ArticleRank_Plugin\', \'updateDayCount\');
        return _t($info);
    }
 
    /**
     * 禁用插件方法,如果禁用失败,直接抛出异常
     * 
     * @static
     * @access public
     * @return void
     * @throws Typecho_Plugin_Exception
     */
    public static function deactivate()
    {
        /**删除数据表*/
        $info = ArticleRank_Plugin::uninstallTable();
        return _t($info);
    }
    
    /**
     * 获取插件配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form 配置面板
     * @return void
     */
    public static function config(Typecho_Widget_Helper_Form $form){}
 
    /**
     * 个人用户的配置面板
     * 
     * @access public
     * @param Typecho_Widget_Helper_Form $form
     * @return void
     */
    public static function personalConfig(Typecho_Widget_Helper_Form $form){}
    
    /**
     * 插入ranks数据表
     * 
     * @access public 
     * @return void
     */
    public function installTable()
    {
        $installDb = Typecho_Db::get();
		$type = explode(\'_\', $installDb->getAdapterName());
		$type = array_pop($type);
		$prefix = $installDb->getPrefix();
		$ s = file_get_contents(\'usr/plugins/ArticleRank/\'.$type.\'.sql\');
		$ s = str_replace(\'typecho_\', $prefix, $ s);
		$ s = str_replace(\'%charset%\', \'utf8\', $ s);
		$ s = explode(\';\', $ s);
		try {
			foreach ($ s as $ ) {
				$  = trim($ );
				if ($ ) {
					$installDb->query($ , Typecho_Db::WRITE);
				}
			}
			return \'建立ranks数据表,记录文章每天点击量,插件启用成功\';
		} catch (Typecho_Db_Exception $e) {
			throw new Typecho_Plugin_Exception(\'数据表建立失败,请检查原因。错误号:\'.$code);	
		}
    }
    
    /**
     * 删除数据表
     * 
     * @access public
     * @return void
     */
    public function uninstallTable()
    {
        $db = Typecho_Db::get();
        $prefix = $db->getPrefix();
        try
        {
            $db->query($db->query(\'drop table \'.$prefix.\'ranks\'));
            return \'删除ranks数据表,插件已禁止\';
        } catch (Typecho_Db_Exception $e){
            throw new Typecho_Plugin_Exception(\'ranks表删除失败\');
        }
    
    }
    
    /**
     * 加入 beforeRender,更新文章的该天访问量
     * 
     * @access public
     * @return void
     */
    public static function updateDayCount()
    {
        // 访问计数
        if (Typecho_Widget::widget(\'Widget_Archive\')->is(\'single\')) {
            $db = Typecho_Db::get();
            $cid = Typecho_Widget::widget(\'Widget_Archive\')->cid;
            $date = date(\"Y-m-d\",time());
            $row = $db->fetchRow($db->select(\'hits\')->from(\'table.ranks\')->where(\'cid = ? AND date = ?\', $cid, $date));
            if($row)
            {
                //更新hits即可
                $db->query($db->update(\'table.ranks\')->rows(array(\'hits\' => (int)$row[\'hits\']+1))->where(\'cid = ?\', $cid));
            }
            else
            {
                //如果第一次浏览则要插入
                $db->query($db->insert(\'table.ranks\')->rows(array(\'cid\'=>$cid,\'hits\'=>1,\'date\'=>$date)));
            }
        }
    }
 
    /**
     * 获取指定篇数的日排行、周排行、月排行、年排行、总排行文章
     * 
     * 语法:ArticleRank_Plugin::theRankPosts(10,\'week\');
     * 
     * @access public 
     * @param int $num 默认取10篇文章
     * @param string $type 日排行:day,周排行:week,月排行:month,年排行:year, 总排行: 其它
     */
    public static function theRankPosts($num = 10, $type = \'\')
    {
        $db = Typecho_Db::get();
        $options = Typecho_Widget::widget(\'Widget_Options\');
        $num = is_numeric($num) ? $num : 10;
        $handle = $db->select(\'*,sum(hits) as sum\')->from(\'table.ranks\')->join(\'table.contents\', \'table.contents.cid = table.ranks.cid\');
        if($type == \'day\')
        {
            $handle->where(\'date = curdate()\');
        }
        if($type == \'week\')
        {
            $handle->where(\'week(date) = week(now())\');
        }
        elseif ($type == \'month\') 
        {
            $handle->where(\'MONTH(date) = MONTH(now())\');
        }
        elseif ($type == \'year\') 
        {
            $handle->where(\'YEAR(date) = YEAR(now())\');
        }
        $posts = $db->fetchAll(
                $handle->group(\'table.ranks.cid\')
                ->order(\'sum(hits)\', Typecho_Db::SORT_DESC)
                ->limit($num)
                );
        if ($posts) {
            foreach ($posts as $post) {
                $result = Typecho_Widget::widget(\'Widget_Abstract_Contents\')->push($post);
                $post_  = htmlspecialchars($result[\' \']);
                $perma  = $result[\'perma \'];
                echo \"<li><a href=\'$perma \'  =\'$post_ \'>$post_ </a></li>\\n\";
            }
 
        } else {
            echo \"<li>N/A</li>\\n\";
        }
    }
 
}

使用起来就很简单了,如下(输出文章排行前10篇文章):

<?php ArticleRank_Plugin::theRankPosts(10,\'week\');?>


需要注意的是:

这里的点击是基于新的数据表的,如果你的点击还不到10篇,就不会显示完全,另外,刚使用插件因点击过少会出现日排行,周排行,月排行的数据一样,这病没有错误。

好了,提供原始版本下载(ArticleRank.zip) ,后台直接开启插件即可使用!

收藏 打印