Laravel Vuejs 实战:开发知乎 (22)关注用户
在vue组件化之前,先解决逻辑上的代码,然后再用vue重构。
关于关注用户可以参考:
Laravel 6 Tutorial: Build a Follow UnFollow System in PHP from Scratch
推荐的扩展包:Laravel 5 Follow System
Laravel 6 | Follow Unfollow System Example From Scratch
1.建立用户关注用户的表 followers
执行命令:
1 php artisan make:migration create_followers_table
****_create_followers_table.php:
1 <?php 2 3 use Illuminate\Database\Migrations\Migration; 4 use Illuminate\Database\Schema\Blueprint; 5 use Illuminate\Support\Facades\Schema; 6 7 class CreateFollowersTable extends Migration 8 { 9 /** 10 * Run the migrations. 11 * 12 * @return void 13 */ 14 public function up() 15 { 16 Schema::create('followers', function (Blueprint $table) { 17 $table->bigIncrements('id'); 18 $table->unsignedBigInteger('user_id')->index()->comment("被关注的用户的id"); 19 $table->unsignedBigInteger('follower_id')->index()->comment("粉丝用户的id"); 20 $table->timestamps(); 21 }); 22 } 23 24 /** 25 * Reverse the migrations. 26 * 27 * @return void 28 */ 29 public function down() 30 { 31 Schema::dropIfExists('followers'); 32 } 33 } 34 35
接着执行:
1 php artisan migrate
2.模型关联 【添加到User.php中】
1 /** 用户的粉丝 2 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 3 */ 4 public function followers() 5 { 6 //外键是粉丝的id 7 return $this->belongsToMany(self::class, 'followers', 'follower_id', 'user_id')->withTimestamps(); 8 } 9 10 11 /** 用户关注的作者 12 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 13 */ 14 public function following() 15 { 16 //外键是作者的id 17 return $this->belongsToMany(self::class, 'followers', 'user_id', 'follower_id')->withTimestamps(); 18 } 19
3.视图处理:
新建了一个views/users文件夹,存储users相关的视图blade文件:
show.blade.php
1 @extends('layouts.app') 2 @section('content') 3 <div class="container"> 4 <div class="row"> 5 <div class="col-md-8 col-md offset-1"> 6 {{--问题--}} 7 <div class="card"> 8 <div class="card-header"> 9 {{ $question->title }} 10 11 @foreach(['success','warning','danger'] as $info) 12 @if(session()->has($info)) 13 <div class="alert alert-{{$info}}">{{ session()->get($info) }}</div> 14 @endif 15 @endforeach 16 17 @can('update',$question) 18 <a href="{{ route('questions.edit',$question) }}" class="btn btn-warning">编辑</a> 19 @endcan 20 21 @can('destroy',$question) 22 <form action="{{ route('questions.destroy',$question) }}" method="post"> 23 @csrf 24 @method('DELETE') 25 <button type="submit" class="btn btn-danger">删除</button> 26 </form> 27 @endcan 28 29 @forelse($question->topics as $topic) 30 <button class="btn btn-secondary float-md-right m-1">{{ $topic->name }}</button> 31 @empty 32 <p class="text text-warning float-md-right"> "No Topics"</p> 33 @endforelse 34 35 <p class="text text-info float-md-right"> 已有{{ count($question->answers) }}个回答</p> 36 37 </div> 38 <div class="card-body"> 39 {!! $question->content !!} 40 </div> 41 </div> 42 43 44 {{--回答提交form--}} 45 {{--只有登录用户可以提交回答--}} 46 @if(auth()->check()) 47 <div class="card mt-2"> 48 <div class="card-header"> 49 提交回答 50 </div> 51 <div class="card-body"> 52 <form action="{{ route('answers.store',$question) }}" method="post"> 53 @csrf 54 <!-- 回答编辑器容器 --> 55 <script id="container" name="content" type="text/plain" 56 style="width: 100%;height: 200px">{!! old('content') !!}</script> 57 <p class="text text-danger"> @error('content') {{ $message }} @enderror </p> 58 <!--提交按钮--> 59 <button type="submit" class="btn btn-primary float-md-right mt-2">提交回答</button> 60 </form> 61 </div> 62 </div> 63 @else 64 {{--显示请登录--}} 65 <a href="{{ route('login') }}" class="btn btn-success btn-block mt-4">登录提交答案</a> 66 @endif 67 {{--展示答案--}} 68 @forelse($question->answers as $answer) 69 <div class="card mt-4"> 70 <div class="card-header"> 71 @include('users._small_icon') 72 <span 73 class="float-right text text-info text-center">{{ $answer->updated_at->diffForHumans() }}</span> 74 </div> 75 76 <div class="card-body"> 77 {!! $answer->content !!} 78 </div> 79 </div> 80 81 @empty 82 83 @endforelse 84 </div> 85 86 <div class="col-md-3"> 87 <div class="card"> 88 <div class="card-header"> 89 <h2> {{ $question->followers_count }}</h2> 90 <span>关注者</span> 91 </div> 92 <div class="card-body"> 93 <question-follow-button question="{{$question->id}}"id}}"> 94 </question-follow-button> 95 </div> 96 </div> 97 98 <div class="card mt-4"> 99 <div class="card-header"> 100 <h2> 提问者 </h2> 101 </div> 102 <div class="card-body"> 103 @include('users._small_icon') 104 </div> 105 @include('users._user_stats') 106 </div> 107 </div> 108 109 110 </div> 111 </div> 112 @endsection 113 @section('footer-js') 114 @include('questions._footer_js') 115 @endsection 116 117
_user_stats_blade.php
1 <div class="card-footer float"> 2 <div class="text-center float-left mr-4"> 3 <div class="text">提问数</div> 4 <div class="number">{{ $question->user->questions_count }}</div> 5 </div> 6 <div class="text-center float-left mr-4"> 7 <div class="text">回答数</div> 8 <div class="number">{{ $question->user->answers->count() }}</div> 9 </div> 10 <div class="text-center float-left "> 11 <div class="text">粉丝数</div> 12 <div class="number">{{ $question->user->followers->count() }}</div> 13 </div> 14 </div> 15 16
_small_icon.blade.php
1 <div> 2 <img src="{{ $answer->user->avatar }}" class="card-img img-thumbnail imgWrap " 3 style="width: 50px" alt="{{ $answer->user->name }}"> 4 <span class="text text-info">{{ $answer->user->name }}</span> 5 </div> 6 <div class="float-left mt-2"> 7 <form action="#" method="post" class="float-left"> 8 <button type="submit" class="btn btn-sm btn-secondary">关注</button> 9 </form> 10 <div class="float-right"> 11 <question-component></question-component> 12 <a href="#" class="btn btn-sm btn-info ml-2">私信</a> 13 </div> 14 </div> 15 16