typecho 真的很简单的自定义评论列表

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

以前写过一个关于自定义评论的文章,时至如今来看,还是有很多不足的,昨晚再新写主题的时候,也重新写了一次自定义评论,嗯,有了新的理解,因为其实真的很简单,仔细阅读本篇文章,相信你会有收获的。

自定义评论模板到底要怎么做

很简单,可以理解为两步:

  1. 编写自定义评论的模板
  2. 通过php渲染出自定义模板评论

而为什么大多数人不会,其实就是因为官方的文档真的是,如果懂php的人,可能看了一两遍后明白了怎么回事,但是如果是小白入门,纯前端的童鞋,可能看的一脸蒙蔽。

就算是原封不动的copy官方的示例代码也还是会报错,心累...

因为,你不知道他要做什么,我编写了自定义模板函数threadedComments;然后呢???

然而官方啥也没说。(当然,我不能保证这篇教程的绝对正确,但是从我的理解和使用上,还是可以正常运作的)

自定义评论模板的编写

我们可以创建一个用于存放模板的php文件,比如list-template.php

模板本身其实就是一个php的函数,不管那些if啥的代码,其实他就是一个空架子

<?php function threadedComments($comments, $options) { ?>

  ...自定义评论模板具体的html内容

<?php } ?>

那么官方文档中开头那部分$commentClass是做什么的,其实是一个用于设置class的php变量,这个变量需要判断这条评论是文章作者的,还是其他人评论的,然后$commentLevelClass则是用来判断,这条评论是主评论还是子评论

事实上官方在 具体的html内容部分又if判断了一次,这条评论是主评论还是子评论,所以,$commentLevelClass这段我们可以删掉,并不会影响后面的内容,当然,待会我会仔细讲讲这段代码怎么用,因为官方写错啦!

$commentClass

那么,$commentClass我们是需要的,如果你的html样式里面不需要判断这条评论是作者的还是其他人的,那么这块代码,包括$commentClass变量,我们可以去除。

$commentClass = '';
if ($comments->authorId) {
  if ($comments->authorId == $comments->ownerId) {
    $commentClass .= ' comment-by-author';  //如果是文章作者的评论添加 .comment-by-author 样式
  } else {
    $commentClass .= ' comment-by-user';  //如果是评论作者的添加 .comment-by-user 样式
  }
}

$commentLevelClass

$commentLevelClass = $comments->_levels > 0 ? ' comment-child' : ' comment-parent';  //评论层数大于0为子级,否则是父级

再官方的文档中,可以看到开头这么一段代码,咋一看好像没啥问题,但是他在后面的li元素那,也有一个判断:

<li id="li-<?php $comments->theId(); ?>" class="comment-body<?php
  if ($comments->levels > 0) {
    echo ' comment-child';
    $comments->levelsAlt(' comment-level-odd', ' comment-level-even');
  } else {
    echo ' comment-parent';
  }
  $comments->alt(' comment-odd', ' comment-even');
  echo $commentClass;
?>">

仔细看,是不是似曾相识:levelscomment-childcomment-parent> 0

这不就是一样的意思吗???为什么要写两遍,所以,我们可以二选一,可以保留li的if判断,删除上面的$commentLevelClass

也可以保留$commentLevelClass,删除li里面的if判断。但是,如果你要保留$commentLevelClass的话,那么需要把_levels改为levels代码才能正常运行。

而li这边则需要改成:

<li id="li-<?php $comments->theId(); ?>" class="comment-body<?php echo $commentLevelClass;?> <?php if ($comments->levels > 0) { $comments->levelsAlt(' comment-level-odd', ' comment-level-even'); }; $comments->alt(' comment-odd', ' comment-even');?>">

是不是感觉有点麻烦,其实还可以拆分:

<?php echo $commentLevelClass;?>这句就不多说了,又不是瞎子,是吧!

后面这一大段:

<?php if ($comments->levels > 0) {
  $comments->levelsAlt(' comment-level-odd', ' comment-level-even');
};
  $comments->alt(' comment-odd', ' comment-even');
?>

仔细看看,其实就是一个判断这条评论是奇数偶数,然后添加对应class的判断而已,何必这么麻烦,是不是,css的选择器::nth-child(odd):nth-child(even)不香吗???

所以,我个人是建议,这句话干掉他,还我一个干净的html代码。

干掉后代码如下:

<li id="li-<?php $comments->theId(); ?>" class="comment-body <?php echo $commentLevelClass;?>">

就这样,我们完事了。

是不是一下就明白了!

现在对于class变量我们知道了,现在来看具体的html评论代码

html评论代码

先看下预设的php变量

方法作用
<?php $comments->gravatar(); ?>评论者头像(avatar源)
<?php $comments->author(); ?>评论者名字
<?php $comments->permalink(); ?>评论者当前评论的页面和定位,点击可以跳转到该评论位置
<?php $comments->date('Y-m-d H:i'); ?>评论的时间,可以到data查看对应的格式
<?php $comments->reply('Reply'); ?>回复按钮
<?php $comments->content(); ?>评论的内容
id="<?php $comments->theId(); ?>"评论的唯一值id

评论代码只需要在html中套用就行了

<li id="li-<?php $comments->theId(); ?>" class="comment-body <?php echo $commentLevelClass;?>">
  <div class="media" id="<?php $comments->theId(); ?>">
     <?php $comments->gravatar(); ?>
     <div class="media-body">
       <?php $comments->author(); ?>
       <?php $comments->content(); ?>
     </div>
     <div class="media-footer">
       <time><?php $comments->date('Y-m-d H:i'); ?></time>
       <?php $comments->reply('Reply'); ?>
     </div>
  </div>
</li>

一个经典的bootstrap的medai评论卡片就完成了,当然这里还只是单条的评论,如有子评论,我们还需要加上一个判断

<li id="li-<?php $comments->theId(); ?>" class="comment-body <?php echo $commentLevelClass;?>">
  <div class="media" id="<?php $comments->theId(); ?>">
     <?php $comments->gravatar(); ?>
     <div class="media-body">
       <?php $comments->author(); ?>
       <?php $comments->content(); ?>
     </div>
     <div class="media-footer">
       <time><?php $comments->date('Y-m-d H:i'); ?></time>
       <?php $comments->reply('Reply'); ?>
     </div>
  </div>
  <?php if ($comments->children) { ?>
    <div class="comment-children">
       <?php $comments->threadedComments($options); ?>
    </div>
  <?php } ?>
</li>

这样一个完整的评论就产生了,由于子评论嵌套在父评论里面,li的效果会产生padding-left的左间距,所以,回复评论太多,宽度就会不太够,所以,官方再博客后台评论设置那,可以设置最多回复多少条,一般是5条就需要新开回复了。

那么,如果想避免这个情况,就可以再这里调整下嵌套结构,比如,像我的做法是我会将子评论和li做同级处理,当然这个做法不是很符合Ol>Li的结构,但是也没啥好办法吧,2333,看大家的智慧了

完整代码

现在就是合体了

<?php function threadedComments($comments, $options) {
  $commentClass = '';
  if ($comments->authorId) {
    if ($comments->authorId == $comments->ownerId) {
      $commentClass .= ' comment-by-author';
    } else {
      $commentClass .= ' comment-by-user';
      }
    }
  $commentLevelClass = $comments->levels > 0 ? ' comment-child' : ' comment-parent';
?>

/* 自定义评论的代码结构 */
<li id="li-<?php $comments->theId(); ?>" class="comment-body <?php echo $commentLevelClass;?>">
  <div class="media" id="<?php $comments->theId(); ?>">
     <?php $comments->gravatar(); ?>
     <div class="media-body">
       <?php $comments->author(); ?>
       <?php $comments->content(); ?>
     </div>
     <div class="media-footer">
       <time><?php $comments->date('Y-m-d H:i'); ?></time>
       <?php $comments->reply('Reply'); ?>
     </div>
  </div>
  <?php if ($comments->children) { ?>
    <div class="comment-children">
       <?php $comments->threadedComments($options); ?>
    </div>
  <?php } ?>
</li>

<?php } ?>

关于审核提示(不一定是正确的)

官方在文档末尾说:

最新版本更新:首次评论审核提示,在自定义评论代码的适当地方添加以下语句,否则将看不到审核提示语句。

<?php $singleCommentOptions->commentStatus(); ?>

但是这句话使用有问题,最直白的就是:$singleCommentOptions这边变量哪里来的,在threadedComments函数中,找遍天也没有创建过这个变量。

事实上这个$singleCommentOptions需要改为$options

所以实际代码是这个:

<?php $options->commentStatus(); ?>

但是,当我们在评论里面添加这句话的时候,你会发现,他并不是真的智能输出的,不管你这条评论是不是真的在审核,他都会显示文字:您的评论正等待审核!

我在百度找到了一个判断:

<?php if ('waiting' == $comments->status): ?>
  <?php $options->commentStatus(); ?>
<?php endif;?>

通过这个判断来输出是否需要显示审核提示,but,既然我if都能判断了,<?php $options->commentStatus(); ?>这句话反倒可有可无了,因为我可以自己写提示文字啊。

<?php if ('waiting' == $comments->status): ?>
  <span>什么吊评论,还要老子审核!!!</span>
<?php endif;?>

这不香吗???

所以,我感觉这代码真的好尬啊!!!

php渲染出自定义模板评论

现在我们模板已经写好了,是时候让它出现在我们的页面上了。

在我们需要添加评论的页面先引入list-template.php文件

<?php $this->need("components/list-template.php");?>

$this->need()方法,他是相对于当前主题目录的,比如你主题名字叫nmd,那么components就是nmd主题目录下的一个文件夹

nmd 主题文件夹
|
---- components
|----|
|    ----  list-template.php
|
...

大概是这样的一个结构,具体就不细说了,意思到位就行!

引入模板后,我们需要使用<?php $comments->listComments(); ?>这段代码渲染评论,但是要注意,如果你的代码前面,没有声明$comments代码的话,使用这句话就会报错。

那么代码应该是这样:

<?php //评论列表 模板->$comments对象->渲染?>
<?php $this->need("components/list-template.php");?>
<?php $this->comments()->to($comments); ?>
<?php $comments->listComments(); ?>

ok,到这基本上你已经领悟了typecho的自定义评论了!恭喜出师。。。老父亲留下激动的泪水

注意

在评论中点击回复,可能会导致刷新页面,原因是因为在评论的回复表单那(form)元素,没有添加取消回复的代码:

<?php $comments->cancelReply('放弃回复'); ?>

这个代码记得添加到form表单那,当然form表单那边id啥的记得不要删了,按照官方文档那种基本上没啥问题。

而本次教程只是讲怎么自定了评论列表,如果以后有时间,再讲讲怎么自定评论表单吧!

typecho 实现“那年今日”功能
« 上一篇 05-11
Typecho博客Joe主题实现打赏设置
下一篇 » 05-16

评论 (4)

  1. 头像
    Spooky Lv.1   湖南省长沙市
    Windows 10 · Google Chrome
    沙发

    博主您好,我的站是一个公益性质的小学生读书会,2个作用,一是展示,二是报名。之前我用的是第三方小程序报名,略繁琐,现在我打算就用文章底部的评论报名,中间涉及到一个问题,我需要里面可以做表单,填写孩子的名字,选择家长是否同去,这个表单只在“报名”分类中的文章下面才有。可否提供一些帮助,万分感谢。

    回复
    1. 头像
      chen'mo 作者 Lv.6   湖南省邵阳市
      Windows 10 · Google Chrome
      @ Spooky

      这个去找原文的作者看看,文章下面有来源网址,我也只是转载。对这些代码也是小白。表情

      回复
    2. 头像
      Spooky Lv.1   湖南省长沙市
      Windows 10 · Google Chrome
      @ Spooky

      参考页面:https://snail.chiphello.com:65001/index.php/archives/132/

      目前我是要求家长回复“孩子姓名+陪同/不陪同”实现的,这样显得不够优雅。

      回复
  2. 头像
    Spooky Lv.1   湖南省长沙市
    Windows 10 · Google Chrome
    板凳

    感谢作者,写得很棒,求续集,自定评论表单!

    回复