TYPECHO WIKI
每一个作品都值得被记录

Typecho 高级功能制作函数借鉴

Typecho维基君Typecho教程 • 4559次浏览 • 发布 2018-07-11 • 更新 2018-07-11

下面给出typecho的一些高级函数,通过这些你可以引申出更多适合自己的功能(原文出处 sunhua.me):

1,判断文章是否为最近3天更新

<?php
function timeZone($from){
$now = new Typecho_Date(Typecho_Date::gmtTime());
return $now->timeStamp - $from < 3*24*60*60 ? true : false;
}
?>

调用如下:

<?php if(timeZone($this->date->timeStamp)) echo 'New';?>

2,人性化评论时间

<?php
function timesince($older_date,$comment_date = false) {
    $chunks = array(
        array(86400 , '天'),
        array(3600 , '小时'),
        array(60 , '分'),
        array(1 , '秒'),
    );
        $newer_date = time();
        $since = abs($newer_date - $older_date);
        if($since < 2592000){
            for ($i = 0, $j = count($chunks); $i < $j; $i++){
            $seconds = $chunks[$i][0];
            $name = $chunks[$i][1];
        if (($count = floor($since / $seconds)) != 0) break;
            }
        $output = $count.$name.' 前';
        }else{
            $output = !$comment_date ? (date('Y-m-j G:i', $older_date)) : (date('Y-m-j', $older_date));
    }
return $output;
}
?>

调用如下:

<?php echo timesince($comments->created);?>

3,wap客户端判断

<?php
function wap(){
    if(@stristr($_SERVER['HTTP_VIA'],"wap")){
        return true;
    }elseif(strpos(strtoupper($_SERVER['HTTP_ACCEPT']),"VND.WAP.WML") > 0){
        return true;
    }elseif(preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])){
        return true;
    }else{
        return false;
    }
}
?>

调用如下(以加载样式表为例):

<?php if(wap()) { ?>
    <link rel="stylesheet" type="text/css" media="all" href="<?php $this->options->themeUrl('wap.css'); ?>" />
<?php } else { ?>
    <link rel="stylesheet" type="text/css" media="all" href="<?php $this->options->themeUrl('style.css'); ?>"/>
<?php } ?>

4,页面载入时间(服务端):

<?php
function timer_start() {
  global $timestart;
  $mtime = explode( ' ', microtime() );
  $timestart = $mtime[1] + $mtime[0];
  return true;
}
timer_start();

function timer_stop( $display = 0, $precision = 3 ) {
  global $timestart, $timeend;
  $mtime = explode( ' ', microtime() );
  $timeend = $mtime[1] + $mtime[0];
  $timetotal = $timeend - $timestart;
  $r = number_format( $timetotal, $precision );
  if ( $display )
    echo $r;
  return $r;
}
?>

调用如下:

<?php echo 'Loading spends ',timer_stop(), ' s.';?>

5,随机日志

<?php
    function theme_random_posts(){
        $defaults = array(
            'number' => 5,
            'before' => '<ul class="list">',
            'after' => '</ul>',
            'xformat' => '<li><a href="{permalink}">{title}</a></li>'
        );
        $db = Typecho_Db::get();

        $sql = $db->select()->from('table.contents')
            ->where('status = ?','publish')
            ->where('type = ?', 'post')
            ->limit($defaults['number'])
            ->order('RAND()');

        $result = $db->fetchAll($sql);
        echo $defaults['before'];
        foreach($result as $val){
            $val = Typecho_Widget::widget('Widget_Abstract_Contents')->filter($val);
            echo str_replace(array('{permalink}', '{title}'),array($val['permalink'], $val['title']), $defaults['xformat']);
        }
        echo $defaults['after'];
    }
?>

调用如下:

<?php theme_random_posts();?>

拓展应用:随机文章调用随机图片;

<?php
  function theme_random_posts(){
        $defaults = array(
            'number' => 4,
            'xformat' => '{permalink}',
            'xtitle' => '{title}',

        );
        $db = Typecho_Db::get();

        $sql = $db->select()->from('table.contents')
            ->where('status = ?','publish')
            ->where('type = ?', 'post')
            ->limit($defaults['number'])
            ->order('RAND()');
        $result = $db->fetchAll($sql);
        foreach($result as $val){
        $rnd=rand(1,201);
        $rand_img = '/usr/themes/thinkH/images/randarticle/'.$rnd.'.jpg';
        $val = Typecho_Widget::widget('Widget_Abstract_Contents')->filter($val);
            $echo_url = str_replace(array('{permalink}', '{title}'),array($val['permalink'], $val['title']), $defaults['xformat']);
            $echo_title = str_replace(array('{permalink}', '{title}'),array($val['permalink'], $val['title']), $defaults['xtitle']);
            echo '<li><a href="'.$echo_url.'"><img src="'.$rand_img. '"/> </a></li>';
        }
    }
?>

6,本地缓存的读者墙:

<?php
function readers($num=40,$timelimit=2){
$period = time() - $timelimit*2592000; // 时间范围: 2*30 天,单位:秒
$counts = Typecho_Db::get()->fetchAll(Typecho_Db::get()
->select('COUNT(author) AS cnt','author', 'url', 'mail')
->from('table.comments')
->where('created > ?', $period )
->where('status = ?', 'approved')
->where('type = ?', 'comment')
->where('authorId = ?', '0')
->group('author')
->order('cnt', Typecho_Db::SORT_DESC)
->limit($num)
);

$mostactive = '';
$avatar_path = Helper::options()->siteUrl . 'usr/themes/主题/images/avatarCache/';
foreach ($counts as $count) {
    $avatar = $avatar_path . md5(strtolower($count['mail'])) . '.jpg';
    $e = __TYPECHO_ROOT_DIR__ . '/' . 'usr/themes/主题/images/avatarCache/' . md5(strtolower($count['mail'])) . '.jpg';
    if ( !is_file($e)){
    $avatar = 'http://www.gravatar.com/avatar/' . md5(strtolower($count['mail'])) . '?s=38&d=identicon&r=X';
    copy($avatar, $e);
        if ( !is_file($e)){
        $avatar = Helper::options()->siteUrl . 'usr/themes/主题/images/default_avatar.jpg'; //这一段是不必要的只是我无聊的将其加上...
        };
    }
    $c_url = $count['url']; if ( !$c_url ) $c_url = Helper::options()->siteUrl;
    $mostactive .= "<li class='avatarsli'><a href='" . $c_url . "' title='" . $count['author'] . " (" . $count['cnt'] . "条评论)_点此到达Ta的网站' target='_blank' rel='nofollow'><img src='" . $avatar . "' alt='' /></a></li>\n";
}
echo $mostactive;
}
?>

调用如下:
33为调用数量,12为月数(即调用最近12个月的数据);无参数即为默认值;

<?php readers(33,12);?>

7,上下文导航显示自定义文章:

<?php
/**
 * 显示下一个内容的标题链接
 * 
 * @access public
 * @param string $default 如果没有下一篇,显示的默认文字
 * @return void
 */
function theNext($widget, $default = NULL)
{
    $db = Typecho_Db::get();
    $sql = $db->select()->from('table.contents')
              ->where('table.contents.created > ?', $widget->created)
              ->where('table.contents.status = ?', 'publish')
              ->where('table.contents.type = ?', $widget->type)
              ->where('table.contents.password IS NULL')
              ->order('table.contents.created', Typecho_Db::SORT_ASC)
              ->limit(1);
    $content = $db->fetchRow($sql);

    if ($content) {
        $content = $widget->filter($content);
        $link = '<a href="' . $content['permalink'] . '" title="' . $content['title'] . '">Newer»</a>';
        echo $link;
    } else {
        echo $default;
    }
}

/**
 * 显示上一个内容的标题链接
 * 
 * @access public
 * @param string $default 如果没有下一篇,显示的默认文字
 * @return void
 */
function thePrev($widget, $default = NULL)
{
    $db = Typecho_Db::get();
    $sql = $db->select()->from('table.contents')
              ->where('table.contents.created < ?', $widget->created)
              ->where('table.contents.status = ?', 'publish')
              ->where('table.contents.type = ?', $widget->type)
              ->where('table.contents.password IS NULL')
              ->order('table.contents.created', Typecho_Db::SORT_DESC)
              ->limit(1);
    $content = $db->fetchRow($sql);

    if ($content) {
        $content = $widget->filter($content);
        $link = '<a href="' . $content['permalink'] . '" title="' . $content['title'] . '">«Older</a>';
        echo $link;
    } else {
        echo $default;
    }
}
?>

调用如下:

<?php theNext($this); ?>
<?php thePrev($this); ?>

8,文章分页显示为:较新,较旧文章;

<?php $this->pageLink('« 较新的', 'prev'); ?>
<?php $this->pageLink('较旧的 »', 'next'); ?>

9,浏览器及操作系统判断

<?php
//开始判断浏览器
function GetBrowser($agent)
{
    if (preg_match('/MSIE\s([^\s|;]+)/i', $agent, $regs)){ $outputer = 'Internet Explorer' . ' ' . $regs[1];}
    else if (preg_match('/FireFox\/([^\s]+)/i', $agent, $regs)){ $outputer = 'Mozilla FireFox ' . ' ' .  $regs[1];}
    else if (preg_match('/Maxthon([\d]*)\/([^\s]+)/i', $agent, $regs)) { $outputer='Maxthon' . ' ' .  $regs[2];}
    else if (preg_match('/Chrome([\d]*)\/([^\s]+)/i', $agent, $regs)){$outputer='Google Chrome' . ' ' .  $regs[2];}  
    else if (preg_match('/QQBrowser\/([^\s]+)/i', $agent, $regs)){$regg = explode("/",$regs[1]);$outputer = 'QQ浏览器' . ' ' .  $regg[0] ;}
    else if (preg_match('/UC/i', $agent)){$outputer = 'UCWeb' . ' ' . '8.11112510';}
    else if (preg_match('/safari\/([^\s]+)/i', $agent, $regs)){$outputer = 'Apple Safari' . ' ' .  $regs[1];}
    else if (preg_match('/Opera[\s|\/]([^\s]+)/i', $agent, $regs)){ $outputer = 'Opera' . ' ' .  $regs[1];}
    else { $outputer = '其它浏览器';}
echo $outputer;
}
 //开始判断操作系统
function GetOs($agent)
{
    $os = false;
    if (preg_match('/win/i', $agent))
        {if(preg_match('/nt 6.0/i', $agent)){  $os = 'Windows Vista'; }
            else if(preg_match('/nt 6.1/i', $agent)) { $os = 'Windows 7';}
            else if(preg_match('/nt 6.2/i', $agent)){$os = 'Windows 8';}
            else if(preg_match('/nt 5.1/i', $agent)){$os = 'Windows XP';}
            else if(preg_match('/nt 5/i', $agent)){$os = 'Windows 2000';}
             else{ $os = 'Windows'; }
        }
    else if(preg_match('/android/i', $agent)){$os = 'Android';} 
    else if(preg_match('/ubuntu/i', $agent)) { $os = 'Ubuntu';}
    else if(preg_match('/linux/i', $agent)){$os = 'Linux';}
    else if (preg_match('/mac/i', $agent)){$os = 'Mac OS X';}     
    else if (preg_match('/unix/i', $agent)){ $os = 'Unix';}
    else if (preg_match('/symbian/i', $agent)){ $os = 'Nokia SymbianOS';}        
    else{ $os = '其它操作系统'; } echo $os;
}
?>

调用如下:

<?php GetBrowser($comments->agent)?> 
<?php GetOs($comments->agent)?>

10,本地版的Gravatar头像缓存:

<?php
    $u = Helper::options()->siteUrl;
    $p = 'usr/themes/peace/images/avatar/';
    $d = Helper::options()->siteUrl . 'usr/themes/peace/images/d_avatar.jpg';
    $t = 1209600*8; // 时间: 14*8 天, 单位: 秒
    $f = md5(strtolower($comments->mail));
    $a = $u . $p . $f . '.jpg';
    $e = __TYPECHO_ROOT_DIR__ . '/' . $p . $f . '.jpg';
    if ( !is_file($e) || (time() - filemtime($e)) > $t ){
    $a = 'http://www.gravatar.com/avatar/' . $f . '?s=32&d=identicon&r=X';
    copy($a, $e);
        if ( !is_file($e)){
            $a = $d; 
            copy($d, $e);
        };
    };
    if ( filesize($e) < 900 ) copy($d, $e);
?>

<img class="avatar" src="<?php echo $a ?>" alt=""/>

调用:个人喜欢把这样的东西放到单独文件中,然后include调用;注意这里只输出了图片(更大的自定义性)。

11,热评文章:
Typecho原生不支持文章点击次数调用(数据库里木有),你可以用插件来实现,当然也可以用如下函数来调用评论数量最多的文章。

<?php
    function theme_most_commented_posts(){
        $defaults = array(
            'number' => 10,
            'before' => '<ul class="list">',
            'after' => '</ul>',
            'xformat' => '<li><a href="{permalink}">{title}<span>({commentsNum})</span></a></li>'
        );
        $time = time() + 8*60*60;
        $db = Typecho_Db::get();

        $sql = $db->select()->from('table.contents')
            ->where('created <= ?', $time)
        ->where('type = ?', 'post')
            ->limit($defaults['number'])
            ->order('commentsNum',Typecho_Db::SORT_DESC);
        $result = $db->fetchAll($sql);
        echo $defaults['before'];
        foreach($result as $val){
            $val = Typecho_Widget::widget('Widget_Abstract_Contents')->filter($val);
            echo str_replace(array('{permalink}', '{title}', '{commentsNum}'), array($val['permalink'], $val['title'], $val['commentsNum']), $defaults['xformat']);
        }
        echo $defaults['after'];
    }
?>

如下调用:

<?php theme_most_commented_posts();?>

12,自定义分类、标签、搜索、首页等文章分页数量
你可以看到,这实际上用的是Is语法来判断的,所以你需要稍稍了解一丢丢Typecho的is语法.
这部分在《Typecho主题制作常用函数》一文中已经出现过…

<?php
function themeInit($archive) {
if ($archive->is('index')) {
$archive->parameter->pageSize = 7; // 自定义条数(我比较喜欢7这个数字^_^)
}
}
?>

调用:直接写入functions.php中即可生效。

13,timthumb实现文章缩略图
支持远程图片,且实现如果文章无图则随机调用现有图片集(这样可以保证样式的统一性)

<?php
 function img_postthumb($cid){
    $db = Typecho_Db::get();   
    $rs = $db->fetchRow($db->select('table.contents.text')      
        ->from('table.contents')          
        ->where ('table.contents.cid=?',$cid)      
        ->order('table.contents.cid', Typecho_Db::SORT_ASC)      
        ->limit(1)); 
    preg_match_all( "/\<img.*?src\=\"(.*?)\"[^>]*>/i", $rs['text'], $thumbUrl );      
        $img_src=$thumbUrl[1][0];       
        $img_counter = count($thumbUrl[0]);   
        if($img_counter > 0){
        echo $img_src;
        }else{
        $rnd=rand(1,151);
        $rnd_url ='' . $options->themeUrl .'/images/random/'.$rnd.'.jpg';
        echo '/usr/themes/主题/images/random/'.$rnd.'.jpg';
    }
}
?>

调用方法:(timthumb.php在主题根目录)

<img src="<?php $this->options->themeUrl(); ?>timthumb.php?src=<?php echo img_postthumb($this->cid) ?>&h=112&w=180&zc=1&q=70"  />

14,网站背景按时间段自动更换

<?php date_default_timezone_set('Etc/GMT-8'); 
    $hour = date('H');
    if ($hour < 7 ) {
    $image = "图片地址一";  //7点以前显示的图片
}
elseif ($hour < 18 ) {
    $image = "图片地址二";  //下午6点以前显示的图片
}
else {
    $image = "图片地址三";  //下午6点以后显示的图片
}
?>

调用如下:

<?php echo $image ?>

当然这也可以用于整个模板风格的变换,灵活运用即可……
好吧,下面木头同学说不会用,那再多打几个字吧,比如:在header.php中

<link rel="stylesheet" href="<?php $this->options->themeUrl('style.css'); ?>" />

这一行之后,(也就是载入样式之后)再写上刚才的代码,额~或者你可以这么写:

<?php date_default_timezone_set('Etc/GMT-8'); 
    $hour = date('H'); 
    if ($hour < 7 ) { 
    $style = 1; 
} 
elseif ($hour < 18 ) { 
    $style = 2;  
} 
else { 
    $style = 3; 
} 
?>

继续小白性质的解说:
那么在不同时段里变量$style就有了不同的值;下面再通过调用样式来用上这个值:

<link rel="stylesheet" href="<?php $this->options->themeUrl('css/'); ?><?php echo $style ;?>.css" />

那么现在,在你主题目录下就该有个CSS文件夹,里面有1.css,2.css,3.css……
当然还可以更多,你可以把需要“根据时间而不同的地方”在这个对应的css文件里写。
这样说得够清楚了吧。
甚至,你还可以这样:

<?php date_default_timezone_set('Etc/GMT-8'); 
    $hour = date('H'); 
    if ($hour < 7 ) { 
    <?php include('include/theme1.php');?>
} 
elseif ($hour < 18 ) { 
    <?php include('include/theme2.php');?>
} 
else { 
    <?php include('include/theme3.php');?>
} 
?>

像这样单独文件的来调用,那么这里面可以写的东西可就更多,更具可变性了,你可以在里面写不同的模块,独立的板式,甚至…
好吧,这样说应该很彻底了吧,阿门……

15,文章页面编辑文章和评论

<?php if($this->user->hasLogin()): ?>
<a href="<?php $this->options->adminUrl('write-post.php?cid=' . $this->cid); ?>">编辑文章</a>
<?php endif; ?>
<?php if($this->user->hasLogin()): ?>
<a href="<?php $this->options->adminUrl('manage-comments.php?cid=' . $this->cid); ?>">编辑评论</a>
<?php endif; ?>
广告声明:文内含有的对外跳转链接(包括不限于超链接、二维码、口令等形式),用于传递更多信息,节省甄选时间,结果仅供参考,Typecho.Wiki所有文章均包含本声明。
厂商投放

【腾讯云】🎉五一云上盛惠!云服务器99元/月续费同价!

腾讯云五一劳动节海量产品 · 轻松上云!云服务器首年1.8折起,买1年送3个月!超值优惠,性能稳定,让您的云端之旅更加畅享。快来腾讯云选购吧!

广告
添加新评论 »