通常我们在PHP开发过程中遇到有交互环节,通常会使用cookies或者session来记录一些用户变量。
同时我们在做wordpress开发时,程序本身给我们提供了很多的hook(钩子),用来在特定的环节执行相关的代码。
一句话总结
wp_head钩子不支持写入session和cookies,init钩子支持写入,但不能获取到wp_query的内容,wp钩子可剪得两者!
这里通过一个示例来说一下在使用wp_head钩子想要写入cookies或者session的坑。
具体需求是这样的:
我们在做一个文章浏览次数统计的时候,默认情况是用户每刷新一次页面就增加一次访问量;代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//阅读数处理 function addrandviews() { if (is_single()) { global $post; $post_ID = $post->ID; if ($post_ID) { $rdno = 1; $posts_views = (int) get_post_meta($post_ID, 'views', true); if (!update_post_meta($post_ID, 'views', ($posts_views + $rdno))) { add_post_meta($post_ID, 'views', 1, true); } } } } add_action('wp_head', 'addrandviews'); |
可以看到我们使用的钩子是wp_head,这个时候,用户每刷新一次都能增加一次访问量,即使是同一个用户!
下面的需求是同一个用户无论刷新多少次都只记录一次访问量:
我们思路是,在访问量增加后使用SESSION或者COOKIES 来记录用户已经访问过该篇文章了;代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
function addrandviews() { if (is_single()) { global $post; $post_ID = $post->ID; $wboxreadposts = array(); if(isset($_COOKIE['wboxreadposts'])){ $wboxreadposts = explode('|',$_COOKIE['wboxreadposts']); } if ($post_ID && !in_array($post_ID, $wboxreadposts)) { $rdno = 1; $posts_views = (int) get_post_meta($post_ID, 'views', true); if (!update_post_meta($post_ID, 'views', ($posts_views + $rdno))) { add_post_meta($post_ID, 'views', 1, true); } if(count($wboxreadposts) > 20) $wboxreadposts = array(); //限制cookies大小 $wboxreadposts[] = $post_ID; setrawcookie("wboxreadposts", implode('|',$wboxreadposts) , time() + 2592000, COOKIEPATH, COOKIE_DOMAIN); } } } add_action('wp_head', 'addrandviews'); |
以上的代码看似没有问题,但在实际的测试中,cookies并没有写入,我们再测试session,同样没有写入,我们又测试了直接在functions.php内放入写入cookies和session的代码,结果是写入成功了的,
这时我们得出的结论是wp_head钩子是不能写cookies和session的。
我们查看了wordpress官方给出的文档:
大致意思是,写入cookies的代码是挂在 init的钩子中的,而读取是放到wp_head钩子中的。
这时,我们立马把wp_head换成了init,新的问题出现了:
使用init钩子时,is_single()函数无效,同时也没有$post全局变量;
通过查阅wordpress的hook文档,找到了可以解决问题的钩子: wp
这个钩子是在主查询生成后执行的,所以这里可以写入cookies和session,也可以判断是否为文章页。问题终于得到解决。