通过插件在《head/》中写入css和js文件

想借助jQuery提升StatPressCN的表现性能,阅读文档过程中突然想到一个问题。jQuery以及自己拟写的js文件需要在<head/>中载入,但wordpress封闭了页面的生成过程,这就意味着用户访问时产生的页面都是通过wp自动生成的,那我怎么有机会引入自己写的css或js文件呢?

后来想应该有hook可以挂接的。查询研读codex并通过研究其他插件的做法(比如wp-stats),果不其然,万能的wp果然提供了这些接口。

先看下wp-stats的做法。

### Function: Enqueue Stats Stylesheets
add_action(‘wp_print_styles’, ‘stats_stylesheets’);
function stats_stylesheets() {
if(!function_exists(‘pagenavi_stylesheets’)) {
if(@file_exists(TEMPLATEPATH.’/stats-css.css’)) {
wp_enqueue_style(‘wp-stats’, plugins_url(get_stylesheet_directory_uri().’/stats-css.css’), false, ‘2.50’, ‘all’);
} else {
wp_enqueue_style(‘wp-stats’, plugins_url(‘wp-stats/stats-css.css’), false, ‘2.50’, ‘all’);
}
}
}
给wp_print_styles添加了一个动作,这个动作通过wp_enqueue_style把自定义的css给链入了html的head部分。稍作修改在StatPressCN中测试,查看源码显示如下:《link rel=’stylesheetid=’statpresscn-csshref=’http://localhost/wp-content/plugins/statpresscn/statpresscn.css?ver=1.7.3.0′ type=’text/cssmedia=’all‘ /》。引入成功。

wp_enqueue_style的功能是“把一个css样式文件纳入队列(显示)”,语法wp_enqueue_style( $handle, $src, $deps, $ver, $media ),handle指的是样式表的名称(必填);src是相对根目录的路径,取值可以是字符串也可以是布林值;deps是指该样式表需要依赖的其他样式表列表,取值应该是数组;ver是指样式表的版本号,意在通知客户端浏览器采用新的样式表;media指该样式表的媒体类型。

样式表加载的相关函数有四个:显示,注册,注销和队列。WP_Styles – CSS stylesheet loading (and functions wp_print_styles, wp_register_style, wp_deregister_style, wp_enqueue_style )

js脚本的载入方法和css类似,仅仅是名称随之换成了scripts而已。WP_Scripts – JavaScript loading (and functions wp_print_scripts, wp_register_script, wp_deregister_script wp_enqueue_script)。

但脚本的加载因为兼容性等原因,要比样式表复杂一些。挂接点一般在init而不是wp_head(可能也行,但我测试没有成功),另外就是对jQuery的调用。因为wordpress系统自身是支持jQuery的,需要使用的时候声明一下就行了,如果想用自己想要的其他版本,那就先注销wp系统的那个,再注册自己的那个。测试成功的代码如下:

// Function: Enqueue StatPressCN javascripts

function spcn_javascripts() {

if (function_exists(‘wp_enqueue_script’)) {

wp_enqueue_script(‘jquery’);

wp_enqueue_script(‘statpresscn’, plugins_url(‘statpresscn/statpresscn.js’), array(‘jquery’), SPCVERSION);

}

}

add_action(‘init’,’spcn_javascripts’);

从测试效果看,在页面的head部分确实是先引入了jquery,然后才是statpresscn.js。因为wp给jQuery设置了防冲突模式,在调用对象的时候不能直接向平常那样通过$调用。要用平常习惯的方式的话,需要做些封装传递
jQuery(document).ready(function($) {
$(‘#statpresscn  li:nth-child(odd)’).addClass(‘gray’);
});
wordpress官方文档中一些参考资源很不错,值得一看。

StatPressCN,1.6.9.9版本

功能开发:

  1. 在朋友来访栏目中为朋友添加头像(gravatar),更直观;
  2. 增加了对朋友留言情况的统计显示,总留言数,最近一次留言时间和内容;
  3. 增加对朋友总访问数的统计显示;
  4. 丰富了详情中的内容,增加了直接点击发邮件给朋友的功能。

def规则:

  1. 搜索引擎数据定义:新增了对Google mobile的支持,www.google.cn/m;lai79的识别,www.lai79.com;
  2. 爬虫数据:北大学生爬虫的识别,PKU Student spider。

代码改进:

  1. 更新了部分本地化语言;
  2. 修正了对sharethis识别逻辑;
  3. 彻底解决了朋友中仍显示垃圾评论者的问题。

下载升级:

  • 请到wordpress官方插件网址下载最新版本,ftp到服务器上去;
  • 或者,如果您的wordpress是2.7版本以上的,那就耐心等段时间(大约几个小时吧),管理后台会自动提示升级的;
  • 提示:升级至本版本不会影响数据库中的数据记录。

升级需做:

  • 在StatUpdate(统计升级)中任何选项都不需要选中,执行一次升级(就是点那个升级按钮),作用是清理垃圾评论者的访问记录。

开发笔记

对于sharethis的逻辑判断经检查还是出了问题,应该分两层:先判断querystring中是否包含akst_action字样,如果有的话还要看是否包含了p=90之类的链接符号,后者说明blog没有设置永固链接,需要从querystring中提取出文章链接;如果仅包含akst字符串,则放弃querystring,转用requesturi。【换了种思路解决问题简单好多,还有效率也有很大提升,那就是先判断?后是否有p=99之类的硬链接,有的话就提取,并根据是否设定了永固链接获得permalink后存入数据库,如果没有则只取?前的部分直接存入数据库,判断提取语句如下:preg_match(“@(p=\d+|post_id=\d+|page_id=\d+)@”,$urlRequested,$matches)】

wordpress在2.7以上版本中是默认支持gravatar的,用法其实很简单,就是调用get_avatar($email)就ok了。如果要全面,可以加个判断版本低的话直接调用img src,用链接直接调用。

<span>在css中还是比较好用的,一连串的span不会像p那样自动换行。

单复数的问题用?符号最好处理:print $commentleft.” “.($commentleft>1?__(“comments”,”statpresscn”):__(“comment”,”statpresscn”));

在判断是否垃圾评论者的逻辑上,分析如下:先允许所有评论者进来,让Akismet进行过滤,让管理员对首次留言者进行审核,然后再显示朋友来访时再判断是否是正常的朋友留言或访问,通过手动统计更新清除那些垃圾评论者的访问记录(这个应该设定成自动)。

PHP、MYSQL编程笔记

开发StatPressCN过程中恶补PHP和MYSQL知识,水平不行,只好边干边学,呵呵。对一些基础不高深的东东简单梳理下,免得忘了下次重来。

一、MYSQL

  1. 用MYSQL语句直接修改数据。update `db_name` set `urlrequested` = replace(`urlrequested`,’\”,”) where `urlrequested` like “%\'”,把以’结尾的链接请求末尾的’去掉。replace可以保证key的连续性,如果先删除后添加就没有这个好处了。
  2. 插入记录。INSERT INTO users(name, age) VALUES(‘姚明’, 25), (‘比尔.盖茨’, 50), (‘火星人’, 600);如果values中为空,则添加默认值为基础的记录。
  3. 更新记录。需要配合where条件判断。UPDATE users SET age = 30 WHERE id = 12;以上语句都很危险,如果where没有设置的话会更新所有的数据记录,所以在进行类似操作的时候一定要先备份,再审慎
  4. 删除数据有两个命令delete和TRUNCATE。DELETE FROM users WHERE name = ‘Mike’ ORDER BY id DESC LIMIT 6;如果有自动增加的字段,用没有where的delete和truncate都会让这个字段从0开始,如果不想这样,可以用带where 1的语句,不过那样的执行效率很多,因为需要遍历整个数据库的所有记录;删除数据时如果使用形如like ‘$tmpstr%’的语句,一定要判断下$tmpstr是否为空,否则很危险,可能删除掉所有数据,后果严重的很。
  5. 正则表达式在where语句中也可使用,好爽,这下me对正则表达式的学习可以用了。官方文档参见这里。

二、PHP

  1. 分开字符串。$p = explode(“=”,$url);
  2. 打印出数组中的所有元素。print_r($p);
  3. 计算数组中的元素个数。count($p);
  4. 数组运算,类似于java中集合的概念,很方便。生成一个空数组:$bloglist = Array();向数组中增加一个或几个元素(从末尾):array_push($bloglist,$matches[1]);添加到数组头部之前则是array_unshift($bloglist,$matches[1]) ;从数组尾部删除一个元素用array_pop(),从头部删除一个元素则用array_shift();让数组中元素唯一(即无重复元素,类似于结合set的概念):$bloglist = array_unique($bloglist);迭代输出每个元素可以在foreach中使用as:foreach($bloglist as $blog);判断某元素是否在数组中:in_array($lookingFor, $bloglist),返回布尔值真假;数组中每个元素都有个默认的key,可以这样输出看看:while (list($key,$value) = each($bloglist)) {echo “$key : $value<br>”;};还可以合并多个数组$bloglistall = array_merge($bloglist1, $bloglist2);得到两个数组的交集可用array_intersection($bloglist1, $bloglist2);差集可用array_diff($bloglist1, $bloglist2);如需要合集则先array_merge(),然后再用一次array_unique();对数组进行排序则用sort($bloglistall),默认是英文字母顺序;数组的key必须是唯一的,并且key可以设定为字符串,默认是整数。关于数组,更详细的阐释是Array的官方说明(e文版)。
  5. 奇妙的类型自动转换。print(“8&heart5″+20);输出结果为28。
  6. 字符串函数:strlen,得到字符串长度;substr($v,start_pos,length),截取指定长度的字符串,不指定长度则自动取到末尾;strripos($v,”postname”),是否包含指定子字符串,返回所处位置或;sscanf,扫描规律字符串得到相应变量;printf,格式化输出字符串;str_replace,替换子字符串;strstr,找到特定子字符串出现的位置;rtrim会删除末尾的空格和换行等字符,包括空格、\t、\n、\r、\0、\x0b;explode会自动处理行尾的空字符。
  7. 正则表达式。ereg(‘^/[0-9]{4}/[0-9]{2}/{0,1}$’,$out_url);匹配/2008/10
  8. 时间函数。println(strtotime(“now”));输出1224902867,然后用date函数格式化println(date(“c”,$d1));输出2008-10-24T18:03:42+08:00,println(date(“r”,$d1));输出Fri, 24 Oct 2008 18:03:42 +0800,如果用gmdate则输出格林威治标准时,println(gmdate(“r”,$d1));输出Fri, 24 Oct 2008 10:03:42 +0000;其中时区信息是通过date_default_timezone_set(‘prc’);设定的,prc指中国大陆,也可以是其他,有效值列表见这里;另外strtotime还可以对时间做修正,比如strtotime(“3 October 2005”)和strtotime(“1 days”,strtotime(“2 October 2005”))输出的结果都是一样的,可以用的修正符号有“+1 week 3 days 7 hours 5 seconds”,可以用+-号。
  9. file打开某个文件并把每行读入数组;fopen打开一个文件返回句柄,可以设定打开方式为读或者写,打开后内容置空;fwrite则写入内容,成功则返回true,否则是false;操作完毕后需要fclose关闭句柄。

三、WordPress

  1. get_option直接得到选项值,不用每次用mysql语句查询。
  2. get_permalink($id)得到帖子的固定链接地址,注意是包含域名的绝对路径,如果需要相对路径,则需要str_replace(get_bloginfo(“url”),””,get_permalink($id));
  3. update_option如果该项不存在会自动建立。技巧:如果不能确定某个选项是否存在,则可以先update后再delete。
  4. 数组可以一次性存入option中,存储形如a:2:{s:5:”title”;s:8:”my titile”;s:4:”body”;s:12:”Home is warm”;},a指的数组,2是元素个数,title是key名称,5是字符串长度,my titile是title的值,后面body同。
  5. 要调用插件或主题中的函数必须进入wp的主题运作机制,直接调用是无效的,出于安全考虑,同时也是因为无法得到相关环境设定和变量。官方提供的方式是模板,比如您可以自己定义一个page的新模板,然后创建page是选择新模板就可以了。模板标头有特殊要求,见这里
  6. php代码执行其实是以用户权限进行的,因为可以获取文件的在服务器上的本地地址并进行读写操作。

四、HTML

  1. 因为php可以控制输出逻辑,因此可以尽量使用html代码而不是通过php的echo或print输出,这样页面逻辑更清晰,也容易调试。
  2. 表格需要设定宽度后,表格单元中的左对齐右对齐才能起作用。
  3. input type=checkbox name=’statpress_showhotdepth’ value=’checked’ xxx

五、CSS

  1. 样式表嵌入标签的方法。<table class=’mytable’>……</table>,这种情况下mytable应该在外链的css或者当前页面自定义的css中已经定义过;或者直接写style:<table style=”outline:dotted 1px green;”>……</table>
  2. 在形如#sidebar h2{……}中,仅对那些class是sidebar中出现的h2才起作用。

订阅数量统计

昨天的聚合输出乱码把me的关注点吸引到feed、rss等相关的东东方面来。虽然输出乱码的问题已经暂时解决,但me对feedburner的价值认同大幅度降低,不能再完全依靠它,再次使用其feedflare功能发现超慢之后me就更是无法留恋了。

到WP后台停掉了FeedBurner FeedSmith插件,它的作用是把所有对原生聚合输出的存取都自动转向到feedburner去。这样与feed相关的插件就只剩下Feed CountFeed Statistics了。两个都是统计订阅数的,前者针对feedburner,把由其托管的订阅数提取出来,后者则针对原生输出的订阅进行统计。me从来没有用过feedsky等其他烧录服务,因此从理论上讲这两个的统计之和应该就是“天高云淡”的总订阅数。好,下面的任务就是把总订阅数动态显示在侧栏

Feed Count的官方网站这几天一直处于维护状态,没有更详细的资料,好像也不支持widget,只提供了一个函数供调用,如下:

< ?php if (function_exists('fc_feedcount')) fc_feedcount(); ?>

另外Feed Count在WP后台提供了个性化设置界面,可以对上面函数的输出做个性化配置,但是调用该函数后的输出像这样52 位订阅者,不但是字符串不是数值,还带有链接。查看feedcount.php在源码的fc_feedcount函数中发现有这么一部分:

        if (trim($map_fc_link)!='') {
$openlink = "";
$closelink="";
}
print "

$openlink\n"; if ($map_fc_before) { print " $map_fc_before\n"; } print "$number\n"; if ($map_fc_after) { print " $map_fc_after\n"; } print "$closelink
";

并且该函数返回值为空,因为它已经把结果print了。其实me只是需要那个$number而已。用一句

return $number;

替代上面代码就OK了。
再来看Feed Statistics,其调用函数feed_subscribers源码如下:

function feed_subscribers(){
$s = FEED_STATS::how_many_subscribers();
echo $s." feed subscriber";
if ($s != 1) echo "s";
}

我们需要的是那个$s,把它返回就行了。
很好,两个数值我们都可以通过调用函数得到了,下面我们来定制输出:
直接订阅

< ?php if (function_exists('feed_subscribers'))
$stat_or=feed_subscribers();
print $stat_or; ?>

人,通过feedburner订阅

< ?php if (function_exists('fc_feedcount'))
$stat_fb=fc_feedcount();
print $stat_fb ?>

人;本站共计有

< ?php print $stat_or+$stat_fb;?>

人订阅。不过这样好像不大美观,并且内容复杂,me去feedburner网站下了两个小图标上传至服务器,效果见页面左上角,最终代码如下:

	
  • 订阅统计

  • < ?php if (function_exists('feed_subscribers')) $stat_or=feed_subscribers(); print $stat_or; ?>人,
     
    < ?php if (function_exists('fc_feedcount')) $stat_fb=fc_feedcount();print $stat_fb ?>人;共计
    < ?php print $stat_or+$stat_fb;?>人订阅。

    至于进一步的美化就需要您自己设计css了,呵呵。