Typecho 主题开发 - 点赞功能

chen'mo
2021-05-20 / 0 评论 / 3,796 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2021年05月20日,已超过1311天没有更新,若内容或图片失效,请留言反馈。

Typecho 默认是没有提供点赞相关的 API 的,点赞功能只能自己开发,点赞也需要涉及到数据库操作。这里就以 我的博客主题 点赞功能为例,简单写一下点赞功能的开发。

编写函数
Typecho 提供了一个 functions.php,可以用来定义函数,数据库相关的操作就放在 functions.php 中。

下面编写两个函数,agreeNum 函数用来获取点赞数量,agree 函数用来点赞。

agreeNum 函数:

function agreeNum($cid) {
    $db = Typecho_Db::get();
    $prefix = $db->getPrefix();
    
    //  判断点赞数量字段是否存在
    if (!array_key_exists('agree', $db->fetchRow($db->select()->from('table.contents')))) {
        //  在文章表中创建一个字段用来存储点赞数量
        $db->query('ALTER TABLE `' . $prefix . 'contents` ADD `agree` INT(10) NOT NULL DEFAULT 0;');
    }

    //  查询出点赞数量
    $agree = $db->fetchRow($db->select('table.contents.agree')->from('table.contents')->where('cid = ?', $cid));
    //  获取记录点赞的 Cookie
    $AgreeRecording = Typecho_Cookie::get('typechoAgreeRecording');
    //  判断记录点赞的 Cookie 是否存在
    if (empty($AgreeRecording)) {
        //  如果不存在就写入 Cookie
        Typecho_Cookie::set('typechoAgreeRecording', json_encode(array(0)));
    }

    //  返回
    return array(
        //  点赞数量
        'agree' => $agree['agree'],
        //  文章是否点赞过
        'recording' => in_array($cid, json_decode(Typecho_Cookie::get('typechoAgreeRecording')))?true:false
    );
}

上面的函数很简单,下面是说明:

判断存储点赞数量的字段是否存在。
如果点赞数的字段不存在就创建。
查询出点赞数量。
获取点赞记录的 Cookie。
判断文章是否点赞过。
返回点赞数量和点赞记录。
上面的 agreeNum 函数调用的时候需要传入一个 cid,cid 就是 Typecho 的文章 ID。

agree 函数:

function agree($cid) {
    $db = Typecho_Db::get();
    //  根据文章的 `cid` 查询出点赞数量
    $agree = $db->fetchRow($db->select('table.contents.agree')->from('table.contents')->where('cid = ?', $cid));

    //  获取点赞记录的 Cookie
    $agreeRecording = Typecho_Cookie::get('typechoAgreeRecording');
    //  判断 Cookie 是否存在
    if (empty($agreeRecording)) {
        //  如果 cookie 不存在就创建 cookie
        Typecho_Cookie::set('typechoAgreeRecording', json_encode(array($cid)));
    }else {
        //  把 Cookie 的 JSON 字符串转换为 PHP 对象
        $agreeRecording = json_decode($agreeRecording);
        //  判断文章是否点赞过
        if (in_array($cid, $agreeRecording)) {
            //  如果当前文章的 cid 在 cookie 中就返回文章的赞数,不再往下执行
            return $agree['agree'];
        }
        //  添加点赞文章的 cid
        array_push($agreeRecording, $cid);
        //  保存 Cookie
        Typecho_Cookie::set('typechoAgreeRecording', json_encode($agreeRecording));
    }

    //  更新点赞字段,让点赞字段 +1
    $db->query($db->update('table.contents')->rows(array('agree' => (int)$agree['agree'] + 1))->where('cid = ?', $cid));
    //  查询出点赞数量
    $agree = $db->fetchRow($db->select('table.contents.agree')->from('table.contents')->where('cid = ?', $cid));
    //  返回点赞数量
    return $agree['agree'];
}

上面的函数也很简单,下面是说明:

获取点赞记录的 Cookie。
如果 Cookie 不存在就创建一个。
判断文章是否点赞过。
如果文章点赞过就不再往下执行。
把文章的 cid 添加到点赞记录的 Cookie 中。
更新点赞字段。
查询出点赞数量。
返回点赞数量。
点赞记录的 Cookie 是一个 JSON 字符串,需要读取或更改的时候就需要转换为 PHP 对象,更改完成后需要转换为 JSON 字符串写入 Cookie。

点赞记录的 Cookie 中保存着文章的 cid,每次点赞 文章的 cid 就会被加到 Cookie 中。如果要判断文章是否点赞过就可以判断文章的 cid 是否存在。

文章页
Typecho 用来输出文章的文件是 post.php,处理点赞和展示点赞数量就需要在这个文件中编写。

下面是处理点赞的部分:

//  判断是否是点赞的 POST 请求
if (isset($_POST['agree'])) {
    //  判断 POST 请求中的 cid 是否是本篇文章的 cid
    if ($_POST['agree'] == $this->cid) {
        //  调用点赞函数,传入文章的 cid,然后通过 exit 输出点赞数量
        exit(agree($this->cid));
    }
    //  如果点赞的文章 cid 不是本篇文章的 cid 就输出 error 不再往下执行
    exit('error');
}

上面的点赞处理需要放到 post.php 的顶部,也就是放到 HTML 代码的前面。这里如果判断是点赞请求就只会处理点赞,不会往下执行。

我的点赞数量是显示在点赞按钮中的,下面是显示输出点赞数量和点赞按钮。

获取点赞数量:

<?php $agree = $this->hidden?array('agree' => 0, 'recording' => true):agreeNum($this->cid); ?>
上面首先判断文章是否加密,如果加密就把点赞数设置为 0,然后禁止点赞,否则就调用函数获取点赞数量。

点赞按钮:

<button <?php echo $agree['recording']?'disabled':''; ?> type="button" id="agree" data-cid="<?php echo $this->cid; ?>" data-url="<?php $this->permalink(); ?>">
  <span>赞</span>
  <span class="agree-num"><?php echo $agree['agree']; ?></span>
</button>

注意文章按钮有两个自定义属性,data-cid 存储文章的 cid,JS 发送 AJAX 请求的时候会用到,data-url 文章的 URL,发送 AJAX 请求的 URL。

上面如果文章被点赞过 PHP 就会输出 disabled 来禁用按钮。

JavaScript 点赞
我这里用到了 jQuery,下面是点赞代码:

//  点赞按钮点击
$('#agree-btn').on('click', function () {
  $('#agree-btn').get(0).disabled = true;  //  禁用点赞按钮
  //  发送 AJAX 请求
  $.ajax({
    //  请求方式 post
    type: 'post',
    //  url 获取点赞按钮的自定义 url 属性
    url: $('#agree-btn').attr('data-url'),
    //  发送的数据 cid,直接获取点赞按钮的 cid 属性
    data: 'agree=' + $('#agree-btn').attr('data-cid'),
    async: true,
    timeout: 30000,
    cache: false,
    //  请求成功的函数
    success: function (data) {
      var re = /\d/;  //  匹配数字的正则表达式
      //  匹配数字
      if (re.test(data)) {
        //  把点赞按钮中的点赞数量设置为传回的点赞数量
        $('#agree-btn .agree-num').html(data);
      }
    },
    error: function () {
      //  如果请求出错就恢复点赞按钮
      $('#agree-btn').get(0).disabled = false;
    },
  });
});

点赞后被点赞的文章的点赞按钮会被禁用,只有点赞记录的 Cookie 到期或清除后才能再次点赞。

以上就是 Typecho 点赞功能的代码和详细说明,上面的函数和代码放到其它主题中也能使用,JS 部分需要依赖 jQuery。

那一年 · 5月20日
Typecho博客Joe主题实现打赏设置
« 上一篇 05-16
为Typecho添加webp解析
下一篇 » 05-21

评论 (0)