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

先解释一下路由接口,路由接口的功能就是 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. 欧文斯
      欧文斯 回复

      Windows 10Chrome 79.0.3945.88来自 福建 的大神

      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

        1. 欧文斯
          欧文斯 回复

          Windows 10Chrome 79.0.3945.88来自 福建 的大神

          改个函数名试试

  2. null
    null 回复

    Windows 10Chrome 83.0.4103.116来自 日本 的大神

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

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

    1. 欧文斯
      欧文斯 回复

      Windows 10Chrome 81.0.4044.138来自 福建 的大神

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

      1. null
        null 回复

        Windows 10Chrome 83.0.4103.116来自 日本 的大神

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

        1. 欧文斯
          欧文斯 回复

          Windows 10Chrome 81.0.4044.138来自 福建 的大神

          所谓自定义路由就是使用原本不存在的 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. 欧文斯
            欧文斯 回复

            Windows 10Chrome 81.0.4044.138来自 福建 的大神

            加载 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. 欧文斯
            欧文斯 回复

            Windows 10Chrome 81.0.4044.138来自 福建 的大神

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

          6. 新手
            新手 回复

            Windows 10Chrome 114.0.0.0来自 广东 的大神

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

          7. 欧文斯
            欧文斯 回复

            Windows 10Chrome 106.0.0.0来自 福建 的大神

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

  3. 111
    111 回复

    Windows 10Firefox 80.0来自 上海 的大神

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

    1. 欧文斯
      欧文斯 回复

      Windows 10Chrome 85.0.4183.83来自 福建 的大神

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

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