Typecho 自定义路由接口方法 - 给主题集成 Like 插件点赞喜欢功能

小助手读文章 00:00 / 00:00

先解释一下路由接口,路由接口的功能就是 Typecho 根据客户端的访问请求,找到系统中对应的控制器,然后执行相关功能。可能比较难以理解,下面举个例子说明应该就比较看得懂了。

需求

当下使用较多的点赞功能应该就是 skylzl 大佬开发的 Like 插件了,实际使用中发现在 iOS 浏览器 Safari 环境下,存在可以无限次点赞功能。经排查发现,插件使用 Cookie 来识别是否执行了点赞动作,但是采用的 Cookie 插件对 Safari 支持不好,无法正确写入、读取 Cookie。

基于此问题背景,加上能少装插件就少装插件的目标,故考虑将 Like 核心功能集成到 ArmxMod for Typecho 主题中。

分析

点赞功能按实现流程,可以分为:

前端按钮点赞(JavaScript)--> 后端主题接收请求(PHP)--> 后端主题处理请求并反馈处理结果给前端(PHP) --> 前端根据反馈处理点赞结果(JavaScript)

实现

前端点赞

这部分比较简单,先指定点赞入口:

<a href="javascript:;" class="post-like" data-pid="'.$cid.'" id="pluszan">赞</a>

然后 JavaScript 绑定点击动作,并向后端发出请求:

var likeup = '/action/like?up';
$('.post-like').on('click', function(e){
    var id = $(this).attr('data-pid');
    $.post(likeup,{
        cid:id
    }
});

这里可以看到,我们使用了 Ajax 异步请求,所以应保证网站已经引入 jquery 库。

接收请求

这一部分即是路由接口需要做的事情,当前端点赞时,后端如何知道前端进行了点赞,参照代码:

function themeInit($self) {
......
        if ($self->is('archive',404)){
                $path_info = trim($self->request->getPathinfo(),'/');
                if(strpos($path_info,'action/like') !== false){
                        header( "HTTP/1.1 200 OK" );
                        likeup($self);
                        $self->response->goBack();
                        exit;
                }
        }
......
}

路由接口需要在启用主题时就进行定义,所以应该在接口定义放在 Typecho function.phpthemeInit 功能中。

这里我定义的路由是 /action/like,如果请求匹配到,则执行点赞后端处理函数 likeup()

后端处理

后端主要处理的动作是,当接收到点赞时,对该文章的点赞数进行 +1,并返回 success 标志告诉前端已经处理完成,参照代码:

function likeup($self) {
        $cid = $self->request->filter('int')->cid;
        $self->db = Typecho_Db::get();
        $row = $self->db->fetchRow($self->db->select('likes')->from('table.contents')->where('cid = ?', $cid));
        $self->db->query($self->db->update('table.contents')->rows(array('likes' => (int)$row['likes']+1))->where('cid = ?', $cid));
        $self->response->throwJson("success");
}

前端处理

前端处理这一部分可有可无,如果需要针对后端处理结果,在前端做出响应,就要进一步处理,如果不处理也无大碍就是。需要注意的是,后端处理可能会花费较长时间才会有响应,造成前端困扰,因此鉴于是否响应无关紧要,我们可以直接在前端点赞时就给予反馈,比如提示“点赞成功”等等。

最后,本文中的范例仅作为参考,实际使用应根据环境做相应修改,比如增加请求校验等等。

Q&A

1、Q:为什么已经定义了Header("HTTP/1.1 200 OK");返回的状态码还是 404 Not Found
A:在 Typecho 1.1 版本之后,对状态返回逻辑做了修改,任何类似 Header("HTTP/1.1 200 OK"); 的状态码修改方法都是无效的,具体可参见 Github Issue。解决方法就是利用 Typecho 原生函数来实现:

原来的写法:

header( "HTTP/1.1 200 OK" );
likeup($self);
$self->response->goBack();
exit;

Typecho 1.2 及之后的新写法:

Typecho_Response::getInstance()->setStatus(200)->respond(likeup($self));

参考文章:

1、《Typecho中的路由解析
2、《非插件实现路由[转]


ArmxMod for Typecho
个性化、自适应、功能强大的响应式主题

推广

 继续浏览关于 教程typecho经验开发路由接口插件集成点赞 的文章

 本文最后更新于 2023/06/12 09:52:35,可能因经年累月而与现状有所差异

 引用转载请注明: VirCloud's Blog > Typecho > Typecho 自定义路由接口方法 - 给主题集成 Like 插件点赞喜欢功能

精选评论

  1. Jdeal
    Jdeal 回复

    Mac OS X 10_13_6Chrome 79.0.3945.88来自 江苏 的大神

    接收请求 这段是放到function.php 的 themeInit 里,后端处理 处理这段放哪里的额,博主大大,我加进去前台页面显示 Call to a member function is() on null,是啥原因额,求教,谢谢 icon_surprised.gif

    1. 欧文斯

      function.php 里随便找个地方放都可以,最简单的就是放到最后

      1. Jdeal
        Jdeal 回复

        Mac OS X 10_13_6Chrome 79.0.3945.88来自 江苏 的大神

        加好后还是显示Call to a member function is() on null icon_cry.gif

  2. null
    null 回复

    Windows 10Chrome 83.0.4103.116来自 日本 的大神

    前端点赞那里的post是向likeup发送,路由接口写的是action/like,前端后端的接口路径应该怎么对应的写,我这样写post的返回值都是404页面

    第三行post的括号好像没闭合

    1. 欧文斯

      前端是向 like?up 发送,代码没拷全 icon_mrgreen.gif

      1. null
        null 回复

        Windows 10Chrome 83.0.4103.116来自 日本 的大神

        我写成对应的接口,确实是执行了接口下的命令了,但是这个url指向的是一个404页面,主题初始化函数themeInit里面的$self指向的也是404页面的对象,没有cid属性啥的

        1. 欧文斯

          所谓自定义路由就是使用原本不存在的 URL,所以指向 404 是正常的,但是写完自定义路由还是指向 404,说明这个 URL 没有被 Typecho 截取到。
          需要确认一下前端向哪个 URL 发起请求,后台截取的是不是这个 URL

          1. null
            null 回复

            Windows 10Chrome 83.0.4103.116来自 香港 的大神

            指向是指向404,此时的$this指的也是404页面的对象,但是命令倒是都执行了。看F12后台执行一次就要加载一次404页面,sidbar footer之类的也要完全加载,开销还是蛮大的,我最后还是另开了一个独立页面只加载header来实现了。

          2. 欧文斯

            加载 404 页面,说明路由没有添加成功~~~

          3. null
            null 回复

            Mac OS X 10_15_2Chrome 79.0.3945.130来自 香港 的大神

            我虽然是返回404页面(不管是post还是直接访问,返回码都是404,返回内容也都是动态的404.php页面),但是路由接口下除了那个200状态码的命令其他都正常执行了,post也正常传值了。现在就是好奇如果搞对的话返回的是哪个页面,而此时声明$this的话指向的又是哪个对象

          4. null
            null 回复

            Windows 10Chrome 83.0.4103.116来自 美国 的大神

            哦,应该是和pjax那样子的一样,我再试试

          5. 欧文斯

            返回的是你写的这个路由,执行的函数值

          6. 新手
            新手 回复

            Windows 10Chrome 114.0.0.0来自 广东 的大神

            请问一下这个返回状态码是404的有解决了吗?
            我也是不管怎么弄,都是返回404,按道理header("HTTP/1.1 200 OK");这句是设置返回的状态码是200才对,可是就是没有改变状态码

          7. 欧文斯

            你用的 Typecho 是 1.2 版本吧 ,1.1 之后的版本对方法做了修改,类似 header("HTTP/1.1 200 OK") 这种修改状态码的写法,都是无效的。方法稍后我写到文章里

  3. 111
    111 回复

    Windows 10Firefox 80.0来自 上海 的大神

    抄了半天没成功,原来是后端处理那里漏了一个括号

    1. 欧文斯

      正常正常,想想那种漏掉的是一个点 icon_smile.gif

  4. TYPECHO升级版本,文件修改记录 - 天涯孤旅