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(); } }
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(); } }
2 select2 样式
2.1 select2 下载
手动下载地址 https://github.com/select2/select2/tags
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
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版本的 解决了此问题。