yii2博客学习笔记(三)

技巧库 · stoneyang · 于 3年前 发布 · 2009 次阅读

客套话就不多说了,直接上教程

照例声明,对于第三篇与前篇篇中类似的部分不会太过于详述。觉得不够详细的部分可以参考第一篇。附上链接yii2博客项目笔记(一)yii2博客项目笔记(二)

初步分析

  • 本篇讲述博客评论功能的实现,并支持对评论回复。
  • 数据库设计为评论表和回复表。

一、数据库建立

命令行执行 .\yii migrate/create comment 创建 comment 数据表,然后修改目录 console\migrations 下生成的文件内容如下:

<?php

use yii\db\Migration;

class m160825_032145_comment extends Migration
{
    public function up()
    {
        $tableOptions = null;
        if ($this->db->driverName === 'mysql') {
            // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
        }

        $this->createTable('{{%comment}}', [
            'id' => $this->primaryKey(),
            'post_id' => $this->integer()->notNull(),
            'comment' => $this->string(),
            'status' => $this->integer(1)->notNull()->defaultValue(1),
            'created_at' => $this->integer()->notNull(),
            'updated_at' => $this->integer()->notNull(),
        ], $tableOptions);
        $this->createIndex(
            'idx-comment-post_id',
            'comment',
            'post_id'
        );
        $this->createIndex(
            'idx-comment-created_at_id',
            'comment',
            'created_at'
        );
    }

    public function down()
    {
        echo "m160825_032145_comment cannot be reverted.\n";

        return false;
    }

    /*
    // Use safeUp/safeDown to run migration code within a transaction
    public function safeUp()
    {
    }

    public function safeDown()
    {
    }
    */
}

命令行执行 .\yii migrate/create reply 创建 reply 数据表,然后修改目录 console\migrations 下生成的文件内容如下:

<?php

use yii\db\Migration;

class m160825_032215_reply extends Migration
{
    public function up()
    {
        $tableOptions = null;
        if ($this->db->driverName === 'mysql') {
            // http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
            $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
        }

        $this->createTable('{{%reply}}', [
            'id' => $this->primaryKey(),
            'comment_id' => $this->integer()->notNull(),
            'reply' => $this->string(),
            'status' => $this->integer(1)->notNull()->defaultValue(1),
            'created_at' => $this->integer()->notNull(),
            'updated_at' => $this->integer()->notNull(),
        ], $tableOptions);
        $this->createIndex(
            'idx-reply-comment_id',
            'reply',
            'comment_id'
        );
        $this->createIndex(
            'idx-reply-created_at_id',
            'reply',
            'created_at'
        );
    }

    public function down()
    {
        echo "m160825_032215_reply cannot be reverted.\n";

        return false;
    }

    /*
    // Use safeUp/safeDown to run migration code within a transaction
    public function safeUp()
    {
    }

    public function safeDown()
    {
    }
    */
}

然后在命令行输入 .\yii migrate 数据表就建立完成了,详细操作看yii2博客项目笔记(一)

数据表的增删改查

打开 Gii 工具。选择 Model Generator。依次建立 comment 和 reply 模型。Namespace 选择 common\models。之后向生成的两个文件添加 TimestampBehavior 行为。

然后选择CRUD Generator,生成 comment 和 reply 表的增删改查。详细操作看yii2博客项目笔记(一)

由于删除评论时也要删除评论的回复,所以打开 backend\controllers\CommentController 。添加use common\models\Reply;命名空间。修改actionDelete方法为

    public function actionDelete($id)
    {
        $this->findModel($id)->delete();
        Reply::deleteAll('comment_id > :comment_id', [':comment_id' => $id]);
        return $this->redirect(['index']);
    }

前台显示

评论是显示在文章列表的,打开 frontend/controllers/PostController.php 修改actionItem方法如下

public function actionItem($id)
    {
    	$post = Posts::findOne($id);
        $tags = $post->tags;
        $comments = Comment::findAll([
            'post_id' => $id,
            'status' => 1]);  //获得该文章所有 status 为 1 的评论
        $replys = array();
        foreach ($comments as $comment) {
            $replys[$comment->id] = Reply::findAll(['comment_id' => $comment->id,'status' => 1]);  //根据评论 id 查找所有 status 为 1 的评论,并赋值给$replys数组,
        }

        return $this->render('item',[
            'post'=>$post,
            'tags'=>$tags,
            'comments'=>$comments,    //传递变量到前台
            'replys' => $replys
            ]);
    }

接着修改 frontend/views/post/item.php 内容如下。

<?php
/* @var $this yii\web\View */
use yii\helpers\Html;

$this->title = $post->title;
$this->params['breadcrumbs'][] = ['label' => 'Posts', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<h1><?php echo  $post->title; ?></h1>
<p class="text-muted">作者:<?php echo $post->author; ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;标签:<?php foreach ($tags as $tags) {
	echo "<kbd>".$tags['tag']."</kbd>&nbsp;&nbsp;";
} ?></p>
<p>
    <?php echo yii\helpers\Markdown::process($post->content, 'gfm'); ?>
</p>

<div class="panel panel-default">
  <div class="panel-heading">评论</div>
  <div class="panel-body">
  		<ul class="media-list">
  		<?php $i = 0; foreach ($comments as $comment)   //循环输出所有评论   ?>
 			 <li class="media">
   				 <div class="media-body">
    			                <h4 class="media-heading"><?php echo '第'.++$i.'楼'; ?></h4>
    				            <?php echo yii\helpers\Markdown::process($comment->comment, 'gfm');?>
    			        </div>
    		         </li>
    			<?php
    				if ($reply = $replys[$comment->id]) {
    					echo "<hr>";
    					foreach ($reply as $reply ) {                 //如果评论有回复,循环输出所有回复
                         ?>
    		        <div style="margin-left:30px;"><?php echo yii\helpers\Markdown::process($reply->reply, 'gfm');?></div>
    			<?php }} ?>
                        <a href="javascript:void(0)" onclick="reply(this,<?php echo $comment->id;?>)" style="margin-left:30px;" >回复</a>
                        <hr>
 			<?php } ?>
		</ul>
  </div>
</div>

<?php   //评论表单 ?>
<?= Html::beginForm(['comment/add', 'id' => $post->id], 'post') ?>
<h4>输入评论内容</h4>
<?= \yidashi\markdown\Markdown::widget(['name' => 'comment', 'language' => 'zh'])?>
<br>
<?= Html::submitButton('提交', ['class' => 'btn btn-primary']) ?>

<?= Html::endForm() ?>


<?php   //回复表单 ?>
<div class="hidden" id="reply" style="margin-left:30px;">
<br>
<?= Html::beginForm(['reply/add'], 'post') ?>
<?= Html::hiddenInput('comment_id', 0, ['id' => 'comment_id']);?>
<?= \yidashi\markdown\Markdown::widget(['name' => 'reply', 'language' => 'zh'])?>
<br>
<?= Html::submitButton('提交', ['class' => 'btn btn-primary']) ?>

<?= Html::endForm() ?>
</div>


<script type="text/javascript">
	function reply(reply,comment_id){           //显示回复内容输入框,参数为该元素,和评论id
		$('#comment_id').val(comment_id);  //修该表单  comment_id 的值为该评论的 id
		$('#reply').removeClass('hidden');   //显示回复输入框
		$(reply).after($('#reply'));  //将回复框移到该元素之后

	}
</script>

然后新建 frontend/controllers/CommentController.php,内容为下。

<?php

namespace frontend\controllers;

use common\models\Comment;
use Yii;
class CommentController extends \yii\web\Controller
{
    public function actionAdd($id)
    {
    	$comment = new  Comment();
    	$comment ->post_id = $id;
    	$comment->comment = Yii::$app->request->post('comment');
    	if ($comment->save()) {
          return  $this->redirect(Yii::$app->request->referrer);
    	}
    	echo "string";
    }

}

新建 frontend/controllers/ReplyController.php,内容为下。

<?php

namespace frontend\controllers;

use Yii;
use common\models\Reply;

class ReplyController extends \yii\web\Controller
{
    public function actionAdd()
    {
    	$reply = new  Reply();
    	$reply ->comment_id = Yii::$app->request->post('comment_id');
    	$reply->reply = Yii::$app->request->post('reply');
    	if ($reply->save()) {
    		 return  $this->redirect(Yii::$app->request->referrer);
    	}
    }

}

附上效果图一张,前台未美化,较丑,多见谅

总结

关于评论的功能实现了,再过几天就开学了,课程比较多,博客开发可能就这了,不会在更新了。

本文由 stoneyang 创作,采用 知识共享署名 3.0 中国大陆许可协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。

共收到 3 条回复
echo#13年前 0 个赞

看了一下,写的很详细,但是我有一个疑问,为什么评论和回复都没考虑 user_id ? 这个逻辑是不是有点问题?

PS:代码的排版其实还可以再优化下。 :smile:

stoneyang#23年前 0 个赞

@echo #1楼 之所以没考虑user_id,因为这个文章只是简单的学习分享的,并不是很严谨完善的博客,就没建立用户系统,不过我相信,我写的这些都会的的话,自己添加user_id和其他功能也应该很容易的。

关于排版的问题,这是用为知写的,复制粘贴过来的,没有仔细检查,所以可能有点变化,后面会仔细检查的。

lzhui#33年前 0 个赞

写的真心不错,楼主什么时候继续更博啊

添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册