Laravel 5.8 做个知乎 6 ——话题、select2的使用

1 话题相关表的创建

1.1 话题表

php artisan make:model Topic -m

databasemigrations2021_06_19_225546_create_topics_table.php

    public function up()
    {
        Schema::create('topics', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->text('bio')->nullable();//简介
            $table->integer('questions_count')->default(0);
            $table->integer('follows_count')->default(0);
            $table->timestamps();
        });
    }

 1.2 问题和主题的关系表。用下划线隔开

 php artisan make:migration create_questions_topics_table --create=question_topic

databasemigrations2021_06_19_234032_create_questions_topics_table.php

    public function up()
    {
        Schema::create('question_topic', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->integer('question_id')->unsigned()->index();
            $table->integer('topic_id')->unsigned()->index();
            $table->timestamps();
        });
    }

1.3 生成两个表

php artisan migrate

`topics`和`question_topic`创建成功

1.4 定义两个表的关系

appTopic.php

<?php

namespace App;

use IlluminateDatabaseEloquentModel;

class Topic extends Model
{
    //
    protected $fillable = ['name','questions_count'];
    
    public function questions()
    {
        return $this->belongsToMany(Question::class)
          ->withTimestamps();
    }
    
}
View Code

appQuestion.php

<?php

namespace App;

use IlluminateDatabaseEloquentModel;

class Question extends Model
{
    //fillable为白名单,表示该字段可被批量赋值;guarded为黑名单,表示该字段不可被批量赋值。
    protected $fillable = ['title','body','user_id'];
    
    public function isHidden()
    {
        return $this->is_hidden === 'T';
    }
    
    public function topics()
    {
        //多对多的关系
        //belongsToMany如果第二个参数不是question_topic的话 可以通过第二个参数传递自定义表名
        return $this->belongsToMany(Topic::class,'question_topic')
          ->withTimestamps();
    }
}
View Code

2 select2 样式

2.1 select2 下载

手动下载地址 https://github.com/select2/select2/tags

官网 https://select2.org/

2.2 select2 使用

使用方式 http://select2.github.io/select2/

esourcesviewsquestionscreate.blade.php

@extends('layouts.app')

@section('content')
     @include('vendor.ueditor.assets')
     <div class="container">
         <div class="row justify-content-center">
            <div class="col-md-8 col-md-offset-2">
                <div class="card">
                    <div class="card-header">发布问题</div>
                    <div class="card-body">
                        <form action="/questions" method="post">
                            {!! csrf_field() !!}
                            <div class="form-group">
                                <label for="title"><h5>标题 </h5> </label>
                                <input id="title" type="text" name="title" class="form-control @error('title') is-invalid @enderror" placeholder="标题" value="{{ old('title') }}">

                                @if($errors->has('title'))
                                    <div class="alert alert-danger">
                                        <ul>
                                            <li>{{ $errors->first('title') }}</li>
                                        </ul>
                                    </div>
                                @endif

                                @if ($errors->any())
                                    <div class="alert alert-danger">
                                        <ul>
                                            @foreach ($errors->all() as $error)
                                                <li>{{ $error }}</li>
                                            @endforeach
                                        </ul>
                                    </div>
                                @endif

                            </div>
                            <div class="form-group">
                                <label for="topic"><h5>话题</h5></label>
                                <select  class="js-example-basic-multiple js-example-data-ajax form-control" name="topic[]" multiple="multiple">

                                </select>
                            </div>
                            <div class="form-group">
                                <label for="container"><h5>描述 </h5> </label>
                                <!--text/plain的意思是将文件设置为纯文本的形式,浏览器在获取到这种文件时并不会对其进行处理-->
                                <!-- 转义 {{ old('body') }} -->
                                <!-- 非转义 {!! old('body') !!} -->
                               
                                <!-- 编辑器容器 -->
                                <script id="container" name="body" type="text/plain" style = "height: 200px;">{!! old('body') !!}</script>
                                
                                <button class="btn btn-success pull-right" type="submit">发布问题</button>
                             </div>
                        </form>

                    </div>
                </div>
            </div>
        </div>
     </div>



    @section('my-js')
    <script src="./../js/app.js"></script>
    <link href="./../css/app.css" rel="stylesheet" />
    {{--         jquery不兼容select2 但是app.js可以 vue太奇怪了
    <script src="./../js/jquery.min.js"></script>
    --}}
    {{--<link href="https://cdn.jsdelivr.net/npm/select2@4.0.12/dist/css/select2.min.css" rel="stylesheet" />--}}
    {{--<script src="https://cdn.jsdelivr.net/npm/select2@4.0.12/dist/js/select2.min.js"></script>--}}
    <link href="./../css/select2.min.css" rel="stylesheet" />
    <script src="./../js/select2.min.js"></script>
    <script type="text/javascript">
    let $ = jQuery;
    $(function(){
        $(".js-example-data-ajax").select2({
            tags: true,
            placeholder: '请选择相关的话题',
            minimumInputLength: 1,
            ajax: {
                url: "/api/topics",
                dataType: 'json',
                delay: 250,
                data: function (params) {
                    return {
                        q: params.term, // search term
                        page: params.page
                    };
                },
                processResults: function (data, params) {
                    // parse the results into the format expected by Select2
                    // since we are using custom formatting functions we do not need to
                    // alter the remote JSON data, except to indicate that infinite
                    // scrolling can be used
                    params.page = params.page || 1;

                    return {
                        results: data,
                        pagination: {
                            more: (params.page * 30) < data.total_count
                        }
                    };
                },
                cache: true
            },
            templateResult: formatRepo,
            templateSelection: formatRepoSelection
        });
        function formatRepo (repo) {
            if (repo.loading) {
                return repo.text;
            }

            return "<div class='select2-result-repository clearfix'>"+
            "<div class='select2-result-repository__meta'>" +
            "<div class='select2-result-repository__title'>" +
            repo.name?repo.name:"laravel" +
                "</div></div></div>";
        }

        function formatRepoSelection (repo) {
            return repo.name || repo.text;
        }
    });
    </script>
    @endsection

<!-- 实例化编辑器 -->
<script type="text/javascript">
    //编辑器
    var ue = UE.getEditor('container', {
        toolbars: [
            ['bold', 'italic', 'underline', 'strikethrough', 'blockquote', 'insertunorderedlist', 'insertorderedlist', 'justifyleft','justifycenter', 'justifyright',  'link', 'insertimage', 'fullscreen']
        ],
        elementPathEnabled: false,
        enableContextMenu: false,
        autoClearEmptyNode:true,
        wordCount:false,
        imagePopup:false,
        autotypeset:{ indent: true,imageBlockLine: 'center' }
    });

    ue.ready(function() {
        ue.execCommand('serverparam', '_token', '{{ csrf_token() }}'); // 设置 CSRF token.
    });
</script>
@endsection
View Code

esourcesviewslayoutsapp.blade.php

@yield('my-js')

2.3 api搜索功能

outesapi.php

Route::get('/topics',function (Request $request){
    $topics = AppTopic::select(['id','name'])
      ->where('name','like','%'.$request->query('q').'%')
      ->get();
    return $topics;
});

3 效果演示

项目代码地址 https://github.com/guainttt/laravel-zhihu/releases/tag/v6.0

ps 低版本的select2中文支持不好 后来我换了2-4.1.0版本的 解决了此问题。

 

原文地址:https://www.cnblogs.com/polax/p/14887807.html