Typecho 高级功能制作函数借鉴
下面给出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; ?>