想在文章页插统计代码,该钩哪个点

· zblog · 阅读 8
摘要

想在文章页正文后面插一段统计代码,或者一个广告位,钩哪个点?我的答案是 Filter_Plugin_ViewPost_Template。它在模板渲染之前触发,你能拿到当前文章的完整对象,也能往模板上下文里塞自定义变量。就这两个能力,够用了

想在文章页正文后面插一段统计代码,或者一个广告位,钩哪个点?我的答案是 Filter_Plugin_ViewPost_Template。它在模板渲染之前触发,你能拿到当前文章的完整对象,也能往模板上下文里塞自定义变量。就这两个能力,够用了。

Filter 和 Action 不是一回事

Z-Blog 的钩子分两类。名字里带 Filter 的能改数据,带 Action 的只是通知你一声。这两个混着用,是新手最容易踩的第一脚。

Filter_Plugin_ViewPost_Template 之所以能塞变量,是因为它把 $template 对象本身递给了你。你调 $template->SetTags(),等于往模板上下文里加了一个键。Action 类钩子只丢给你一串参数,改不了什么。

说白了,选钩子先看你要「改」还是要「知道」。要改就往 Filter 里找,只是想知道发生了就往 Action 里找。

先看看模板里能不能直接写

很多人一上来就惦记写插件。真没必要。

如果只是想在正文下方固定位置插一段代码,打开主题的文章模板,在 {$article.Content} 下面加一段 HTML 就完了。一行 PHP 都不用写。

什么时候才轮到钩子?当你的插入内容要跟着数据变——按分类给不同代码、按作者挂不同广告、按发布时间判断是不是过期文章。模板里堆一堆 if 就难看了,这时候挪到钩子里才合理。

用 ViewPost_Template 塞数据

Add_Filter_Plugin('Filter_Plugin_ViewPost_Template', 'mystats_hook');

function mystats_hook($template)
{
    if (!is_object($template)) {
        return;
    }
    $tags = $template->GetTagsAll();
    if (!isset($tags['type']) || $tags['type'] !== 'article') {
        return;
    }
    $article = $tags['article'];
    $html = '<div class="stats">' . $article->Category->Name . '</div>';
    $template->SetTags('mystats_code', $html);
}

模板里加一个 {$mystats_code},内容就出来了。

GetTagsAll() 那一步别省。不判断 type,独立页面、个人中心、搜索页都会被插一遍。这个坑我踩过,当时还以为模板写错了,查了半天。

几个容易翻车的地方

第一,Filter_Plugin_Zbp_Load 里别做重活。它在每次请求最早期就跑了,在里面查数据库或者读文件,全站都跟着慢。另外这个钩子必须跳过 zb_system 和 zb_users/plugin 两个目录,不然后台直接白屏。不是吓唬人,我本地试过。

第二,改完 include.php 记得去后台清一次缓存。主题开着模板编译的话,不清缓存你改的东西根本不会生效,然后你会以为代码没写对。

第三,别在 Filter 里 exit。有人想「拦一下」,结果把后面所有钩子都掐断了,页面输出一半就停在那儿。

判断标准其实就一条:这段逻辑跟着主题走,还是跟着数据走。跟着主题走的,模板里直接写;跟着数据走的,写钩子。剩下的都是细节。为一段统计代码专门写个插件?说实话我不太推荐,太重的做法反而不好维护。