Laravel之评论系统(一)之创建数据库

用Laravel框架开发一个简单的评论系统

image description

Laravel之评论系统(一)之创建数据库

  1. 首先先创建对应的数据库,评论表comments及点赞表comment_thumb,创建数据表命令如下:

评论表comments:


    CREATE TABLE `comments` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
      `user_id` int(10) unsigned NOT NULL,
      `commentable_id` int(10) unsigned NOT NULL COMMENT '文章id',
      `commentable_type` char(255) COLLATE utf8mb4_unicode_ci NOT NULL,
      `is_reply_author` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '是否有回复人(主要用于后台编辑)',
      `reply_author_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '回复人name',
      `content` text COLLATE utf8mb4_unicode_ci NOT NULL,
      `created_at` timestamp NULL DEFAULT NULL,
      `updated_at` timestamp NULL DEFAULT NULL,
      `deleted_at` timestamp NULL DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

点赞表comment_thumb:


    CREATE TABLE `comment_thumb` (
      `id` int(1) unsigned NOT NULL AUTO_INCREMENT,
      `user_id` int(1) NOT NULL COMMENT '用户id',
      `comment_id` int(1) NOT NULL COMMENT '评论id',
      `status` tinyint(1) NOT NULL COMMENT '用户点赞的行为(0:不喜欢,1:喜欢)',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8

  1. OK,数据库创建完成,第一步先创建一个可以提交评论内容的表单

    <form class="am-form am-g" id="comment-form" action="javascript:;" method="POST">
        {{ csrf_field() }}
        <input type="hidden" name="commentable_id" value="{{$post->id}}">
        <input type="hidden" name="commentable_slug" value="{{$post->slug}}">
        <input type="hidden" class="reply_author" name="comment_reply_author" value="">
        <input type="hidden" class="reply_author_name" name="comment_reply_author_name" value="">
        <h3 class="blog-comment">评论</h3>
        <p class="blog-comment" style="font-size: 12px;">请正确评论,不要发一些不和谐或违法的内容,谢谢照顾!<br>评论支持使用Markdown语法!</p>
        <fieldset>
            <div class="am-form-group">
                <textarea class="comment_content" rows="7" placeholder="一字千金" name="content"></textarea>
            </div>
            @if (Auth::guest())
                <p><span class="face-icon" title="添加表情" ><i class="am-icon-smile-o am-icon-md"></i></span><a data-toggle="modal" class="btn btn-default" href="#modal-form" title="登陆后才能评论,点击登陆">登陆后评论</a>
                </p>
            @else
                <p><span class="face-icon" title="添加表情" ><i class="am-icon-smile-o am-icon-md"></i></span><button type="button" class="btn btn-primary comment_btn" title="登陆后才能评论">发表评论</button></p>
            @endif
        </fieldset>
    </form>

关于表情部分,一会再说,先不管。Form中几个隐藏的表单,分别对应文章ID commentable_id文章链接Slug commentable_slug被回复的人的昵称(@昵称) comment_reply_author被回复人的name(用于查看个人中心) comment_reply_author_name

  1. 创建表单提交的Controller及对应的URL,之后添加一个用于处理前端提交过来的方法

    使用命令php artisan make:controller CommentController创建Controller及路由Route::post('/blog/comment','CommentController@index');//评论


    /**
     * 保存评论内容
     * @param  Request $request [description]
     * @return [type]           [description]
     */
    public function index(Request $request){
        $content = $request->get('content');
        if(empty($content) || mb_strlen($content)<10){
            return redirect()->back()->withErrors('评论内容不能为空或者内容少于10个字符!');
        }
        $reply_author = $request->get('comment_reply_author',NULL);
        $reply_author_name = $request->get('comment_reply_author_name',NULL);

        $auth_user_url = auth_user_url(Auth::user()->name);
        
        $new_content = Filter_word($content,$reply_author,$auth_user_url);
        $data = [
            'is_reply_author' =>trim($reply_author),
            'reply_author_name' => $reply_author_name,
            'content' => $new_content,
            'user_id' => Auth::user()->id,
            'commentable_id' => $request->get('commentable_id'),
            'commentable_type' => 'articles'
        ];

        $res = $this->comment->create($data);

        $slug = $request->get('commentable_slug');
        if($res){
            return redirect('blog/'.$slug);
        }
        return redirect()->back()->withErrors('评论失败,请联系管理员!');
    }

OK,今天暂时先说这么多,剩下的下一篇再说。Laravel共用函数创建参考本人的文章Laravel创建全局帮助函数,下面补充上面涉及到的共用方法:


    /**
     * 登陆用户的个人中心url
     * @param  [type] $auth_name [description]
     * @return [type]            [description]
     */
    function auth_user_url($auth_name){
        return url('/user/'.$auth_name);
    }

    /**
     * 屏蔽敏感词
     * @param [type] $str      [description]
     * @param [type] $fileName [description]
     */
    function Filter_word( $str,$reply_author,$auth_user_url)
    {
        //回复型内容,需要给 @author 加个a标签
        //修饰符i表示不区分大小写进行匹配
        $is_need = false;
        if(!empty($reply_author)){
            $str = preg_replace('/'.$reply_author.'/i','<a href="#link-to-user">'.$reply_author.' </a>',$str);
            $is_need = true;
        }
        $path = config('blog.mgc');
        $fileArr = config('blog.mgc_txt');
        //因为preg_replace函数原因,不能一次性处理太大字符串,所以此处被分成好几个部分,分批处理
        foreach ($fileArr as $file) {
            $fullPath = $path.$file;
            $word = checkOneFile($fullPath);
            $str = preg_replace('/'.$word.'/', '***', $str);
        }

        if($is_need){
            $str = preg_replace('/#link-to-user/',$auth_user_url,$str);
        }
        return $str;
    }

    /**
     * 读取单个文件内容,并做处理
     * @param  [type] $fileName 完整文件路径
     * @return [type]           [description]
     */
    function checkOneFile($fileName)
    {
        if ( !($words = file_get_contents( $fileName )) ){     
            return false;
        }

        return preg_replace("/[1,2,3]\r\n|\r\n/i", '|', $words);
    }

关于敏感词库,此处就不贴出来了,具体可以到我的仓库上查看,里面有敏感词库文本文档。

敏感词配置信息


    //敏感词文件路径
    'mgc' => storage_path('app/public').'/mgck',
    'mgc_txt' => [
        '/key.txt',
        '/key1.txt',
        '/key2.txt',
        '/key3.txt',
        '/key4.txt',
        '/key5.txt',
        '/key6.txt',
        '/key7.txt',
        '/key8.txt',
        '/key9.txt',
        '/seqing.txt',
    ],

GitHub码云oschina

END