百度了好多篇文章,用起来都会报错,花了一天时间研究,终于搞明白自定义评论是怎么做的。

typecho的评论模板是comments.php文件,在这个文件,可能会有人在开头加上这句话:

<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>

事实上这句话是不需要的,记得删除它。

自定义评论的基本结构

很多人在看官方的文档时就会迷糊,说了那么多,到底自定义评论的完整结构是啥,这里我就简单列出来,就三个部分。

comments.php
|
---- 自定义评论列表函数
|
---- 评论表单
|
---- 评论列表输出

其中评论表单和评论列表输出是可以相互更换位置的,但是自定义评论列表函数一定要在最上面。

自定义评论列表函数

该函数可以控制评论列表的输出内容,我们可以自定义输出什么东西,什么位置。

<?php function threadedComments($comments, $options) {
    $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 = $comments->_levels > 0 ? ' comment-child' : ' comment-parent';  //评论层数大于0为子级,否则是父级
?>

/* 自定义评论列表部分 */


<?php } ?>

这样写就是基本的起手式了,自定义评论列表写之前我们要知道几个调用的方法。

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

然后我们根据自己的要求写出对应的html结构

/* 自定义评论列表部分 */
<div>
    <?php $comments->gravatar('40', ''); ?>
    <h2><?php $comments->author(); ?></h2>
    <p>评论时间:<?php $comments->date('Y-m-d H:i'); ?></p>
    <div>
    <?php $comments->content(); ?>
    </div>
    <p><?php $comments->reply(); ?></p>
</div>

这样一个基本结构有了,我们还要考虑子评论,也就是该评论的回复评论。

<?php if ($comments->children) { ?>
      <?php $comments->threadedComments($options); ?>
    <?php } ?>

这句话表示如果有子评论,将按照刚刚自定义的评论列表函数输出子评论。也就是说,评论列表永远都是使用同一个模板,不断的嵌套的。

完整代码:

<?php function threadedComments($comments, $options) {
    $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 = $comments->_levels > 0 ? ' comment-child' : ' comment-parent';  //评论层数大于0为子级,否则是父级
?>

/* 自定义评论列表部分 */
<div>
    <?php $comments->gravatar('40', ''); ?>
    <h2><?php $comments->author(); ?></h2>
    <p>评论时间:<?php $comments->date('Y-m-d H:i'); ?></p>
    <div>
    <?php $comments->content(); ?>
    </div>
    <p><?php $comments->reply(); ?></p>
</div>
/*子评论*/
<?php if ($comments->children) { ?>
      <?php $comments->threadedComments($options); ?>
    <?php } ?>

<?php } ?>

这里自定义评论部分结束!

评论表单

表单部分和官方文档一样,可以自行修改,这里就贴代码出来示意一下

<form method="post" action="<?php $this->commentUrl() ?>" id="comment-form" role="form">
            <?php if($this->user->hasLogin()): ?>
            <p><?php _e('登录身份: '); ?><a href="<?php $this->options->profileUrl(); ?>"><?php $this->user->screenName(); ?></a>. <a href="<?php $this->options->logoutUrl(); ?>" title="Logout"><?php _e('退出'); ?> &raquo;</a></p>
            <?php else: ?>
            <p>
                <label for="author" class="required"><?php _e('称呼'); ?></label>
                <input type="text" name="author" id="author" class="text" value="<?php $this->remember('author'); ?>" required />
            </p>
            <p>
                <label for="mail"<?php if ($this->options->commentsRequireMail): ?> class="required"<?php endif; ?>><?php _e('Email'); ?></label>
                <input type="email" name="mail" id="mail" class="text" value="<?php $this->remember('mail'); ?>"<?php if ($this->options->commentsRequireMail): ?> required<?php endif; ?> />
            </p>
            <p>
                <label for="url"<?php if ($this->options->commentsRequireURL): ?> class="required"<?php endif; ?>><?php _e('网站'); ?></label>
                <input type="url" name="url" id="url" class="text" placeholder="<?php _e('http://'); ?>" value="<?php $this->remember('url'); ?>"<?php if ($this->options->commentsRequireURL): ?> required<?php endif; ?> />
            </p>
            <?php endif; ?>
            <p>
                <label for="textarea" class="required"><?php _e('内容'); ?></label>
                <textarea rows="8" cols="50" name="text" id="textarea" class="textarea" required ><?php $this->remember('text'); ?></textarea>
            </p>
            <p>
                <button type="submit" class="submit"><?php _e('提交评论'); ?></button>
            </p>
        </form>

这里我们可以注意到每个input表单元素都有一个required属性,这个属性就是typecho调用表单验证的地方,如果不需要博客自带的验证就可以去掉对应的判断php代码,但是我觉得还是用比较好,没必要自己再去写,现成的不好吗,又能减少代码书写,岂不美哉。

禁止评论

博客可以设置禁止评论,所以在使用表单之前还要判断有没有禁用评论

<?php if ($this->allow('comment')) : ?>
   <!-- 评论表单form放的地方-->
  <?php else : ?>
    <h3><?php _e('评论已关闭'); ?></h3>
  <?php endif; ?>

评论列表输出

  <!-- 回复列表 -->
  <?php $this->comments()->to($comments); ?>
  <?php if ($comments->have()) : ?>
        <!-- 评论头部提示信息 -->
        <h4><?php $this->commentsNum(_t('暂无评论'), _t('仅有一条评论'), _t('已有 %d 条评论')); ?></h4>
        <!-- 评论的内容 -->
        <?php $comments->listComments(); ?>
        <!-- 评论page -->
        <?php $comments->pageNav('&laquo; 前一页', '后一页 &raquo;'); ?>
      </div>
    </div>
  <?php endif; ?>

通过<?php $comments->listComments(); ?>可以直接输出所有的评论,而且是按照最顶部的自定义模板输出的。

完整代码:

<?php function threadedComments($comments, $options) {
    $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 = $comments->_levels > 0 ? ' comment-child' : ' comment-parent';  //评论层数大于0为子级,否则是父级
?>

/* 自定义评论列表部分 */
<div id="<?php $comments->theId(); ?>">
    <?php $comments->gravatar('40', ''); ?>
    <h2><?php $comments->author(); ?></h2>
    <p>评论时间:<?php $comments->date('Y-m-d H:i'); ?></p>
    <div>
    <?php $comments->content(); ?>
    </div>
    <p><?php $comments->reply(); ?></p>
</div>
/*子评论*/
<?php if ($comments->children) { ?>
      <?php $comments->threadedComments($options); ?>
    <?php } ?>

<?php } ?>
<?php $this->comments()->to($comments); ?>
<?php if ($this->allow('comment')) : ?>
   <!-- 评论表单form放的地方-->
   <div id="<?php $this->respondId(); ?>">
      <div> <!-- 取消回复 -->
        <?php $comments->cancelReply(); ?>
      </div>
     <form method="post" action="<?php $this->commentUrl() ?>" id="comment-form" role="form">
              <?php if($this->user->hasLogin()): ?>
            <p><?php _e('登录身份: '); ?><a href="<?php $this->options->profileUrl(); ?>"><?php $this->user->screenName(); ?></a>. <a href="<?php $this->options->logoutUrl(); ?>" title="Logout"><?php _e('退出'); ?> &raquo;</a></p>
              <?php else: ?>
            <p>
                  <label for="author" class="required"><?php _e('称呼'); ?></label>
                <input type="text" name="author" id="author" class="text" value="<?php $this->remember('author'); ?>" required />
            </p>
            <p>
                  <label for="mail"<?php if ($this->options->commentsRequireMail): ?> class="required"<?php endif; ?>><?php _e('Email'); ?></label>
                <input type="email" name="mail" id="mail" class="text" value="<?php $this->remember('mail'); ?>"<?php if ($this->options->commentsRequireMail): ?> required<?php endif; ?> />
            </p>
            <p>
                  <label for="url"<?php if ($this->options->commentsRequireURL): ?> class="required"<?php endif; ?>><?php _e('网站'); ?></label>
                <input type="url" name="url" id="url" class="text" placeholder="<?php _e('http://'); ?>" value="<?php $this->remember('url'); ?>"<?php if ($this->options->commentsRequireURL): ?> required<?php endif; ?> />
            </p>
              <?php endif; ?>
            <p>
                  <label for="textarea" class="required"><?php _e('内容'); ?></label>
                  <textarea rows="8" cols="50" name="text" id="textarea" class="textarea" required ><?php $this->remember('text'); ?></textarea>
              </p>
            <p>
                  <button type="submit" class="submit"><?php _e('提交评论'); ?></button>
              </p>
        </form>
      </div>
  <?php else : ?>
    <h3><?php _e('评论已关闭'); ?></h3>
  <?php endif; ?>

<!-- 回复列表 -->

  <?php if ($comments->have()) : ?>
        <!-- 评论头部提示信息 -->
        <h4><?php $this->commentsNum(_t('暂无评论'), _t('仅有一条评论'), _t('已有 %d 条评论')); ?></h4>
        <!-- 评论的内容 -->
        <?php $comments->listComments(); ?>
        <!-- 评论page -->
        <?php $comments->pageNav('&laquo; 前一页', '后一页 &raquo;'); ?>
      </div>
    </div>
  <?php endif; ?>

自定义评论完成,这才是最正宗的,完美版本。

bug修复

评论列表报错

这次我再次使用的时候出现了一个问题,就是回复列表输出时出现了have()输出null的情况,找了半天发现漏了一句<?php $this->comments()->to($comments); ?>,没有这个$comments变量就不存在,have函数也不存在就会报错,目前已经更正了。

评论头像修复

<?php $comments->gravatar('40', ''); ?>会直接输出一个img元素,所以不需要再套一个img元素,目前已更正

关于评论列表报错的更多理解

由于缺少了指定变量所以报错,而且这个变量还有个地方使用到了,就是点击回复会将评论表单插入到当前回复内容下面,会有一个关闭按钮,这个关闭按钮也需要用到$comments,所以在使用的时候可以把上面那句变量丢在表单元素的上面。

点击回复表单不自动插入到当前评论内容下

原因是因为我忘记给每个评论加上对应的id了,将评论内容加上id

/* 自定义评论列表部分 */
<div id="<?php $comments->theId(); ?>">
    <?php $comments->gravatar('40', ''); ?>
    <h2><?php $comments->author(); ?></h2>
    <p>评论时间:<?php $comments->date('Y-m-d H:i'); ?></p>
<div>

评论审核提示

将下面的代码放入评论的内容后面即可;

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

当然我这里只是讲解了下typecho自定义评论的基本原理,使用的时候估计还是会遇到一些奇奇怪怪的问题,我们可以参考下官方的文档和官方的默认主题里的comments文件,相信你会有很大的收获。

分类: Typecho博客教程 标签: 主题typechoTypecho 自定义评论模板评论

评论

全部评论 16

  1. 木灵鱼儿
    木灵鱼儿
    FireFox Windows 10
    有新版教程啦,想学习的可以博客搜索:评论;或者点开typecho分类
    1. KSNFSFXFFS
      KSNFSFXFFS
      Google Chrome Windows 10
      @木灵鱼儿没有找到新教材啊
      1. 木灵鱼儿
        木灵鱼儿
        FireFox Windows 10
        @KSNFSFXFFS文章名《typecho 真的很简单的自定义评论列表》
  2. KSNFSFXFFS
    KSNFSFXFFS
    Google Chrome Windows 10
    是否考虑[脱单doge][妙啊][OK][星星眼][doge][脸红]
  3. 54646
    54646
    Google Chrome Windows 10
    2424s萨芬
  4. 哈哈
    哈哈
    Google Chrome Windows 10
    怎么添加@用户
  5. 青枫
    青枫
    FireFox Windows 10
    怎么增加一个“评论成功” 这样的提示呢?
  6. 袁某人
    袁某人
    Google Chrome Android
    请问一下博主,有没有输入框插入不到列表里的情况?我给了id,把官方的comments.php复制过来都没用[哭泣]
    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @袁某人我写了一篇新的文章,你可以在博客里搜一下
  7. abctoby
    abctoby
    Google Chrome Windows 10

    评论审核提示代码具体加在哪儿???



    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @abctoby评论内容代码前面或者后面
  8. chenmo
    chenmo
    QQ Browser Android Pie
    如果我只想要管理员才能评论,要加个什么代码?
    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @chenmo那就直接隐藏表单,登录才显示表单
  9. jclser
    jclser
    FireFox Windows 7
    有的主题的说说就是评论做的,然而这样就和其它评论混淆一起了不方便管理。如果能把评论的status改成其它例如suosuo就可以分开了,然而系统默认接口定死这个值的。[tv_白眼]
    1. 木灵鱼儿
      木灵鱼儿
      FireFox Windows 10
      @jclser毕竟这个typecho本身只是做一个博客程序,评论已经够用了,你想搞成想微博那种短文加多评论形式,估计要改很多地方
      1. jclser
        jclser
        FireFox Windows 7
        @木灵鱼儿不是,我就想增加个status的值而已,一个人摸索好难。你这篇蛮有用的,记下以后用。看你的友情链接是写死的,官方有个PageToLinks.php的插件,改改就能变活了。

目录