Laravel Vuejs 实战:开发知乎 (27)对答案进行点赞

1.建表

用户与回答点赞的关系表【多对多关系】

  1 php artisan make:model Vote -m
  1 <?php
  2
  3 use Illuminate\Database\Migrations\Migration;
  4 use Illuminate\Database\Schema\Blueprint;
  5 use Illuminate\Support\Facades\Schema;
  6
  7 class CreateVotesTable extends Migration
  8 {
  9     /**
 10      * Run the migrations.
 11      *
 12      * @return void
 13      */
 14     public function up()
 15     {
 16         Schema::create(‘votes‘, function (Blueprint $table) {
 17             $table->bigIncrements(‘id‘);
 18             $table->unsignedBigInteger(‘user_id‘)->index()->comment("点赞用户的id");
 19             $table->unsignedBigInteger(‘answer_id‘)->index()->comment("被赞答案的id");
 20             $table->timestamps();
 21         });
 22         Schema::table(‘votes‘, function (Blueprint $table) {
 23             //用户表中用户被删除的时候,同步删除votes表user_id列对应的数据行
 24             $table
 25                 ->foreign(‘user_id‘)//本表有一个user_id列
 26                 ->references(‘id‘)//指向了id列
 27                 ->on(‘users‘)//users表中的那个id列
 28                 ->onDelete(‘cascade‘);//users表中id列里面任意一个id数据删除的时候,删除本votes表user_id列对应的数据行
 29
 30             //答案表中答案被删除的时候,同步删除votes表answer_id对应的数据行
 31             $table
 32                 ->foreign(‘answer_id‘)//本表有一个answer_id列
 33                 ->references(‘id‘)//指向了id列
 34                 ->on(‘answers‘)//answers表中的那个id列
 35                 ->onDelete(‘cascade‘);//answers表中id列里面任意一个id数据删除的时候,删除本votes表answer_id列对应的数据行
 36         });
 37     }
 38
 39     /**
 40      * Reverse the migrations.
 41      *
 42      * @return void
 43      */
 44     public function down()
 45     {
 46         Schema::dropIfExists(‘votes‘);
 47     }
 48 }
 49
 50 
  1 php artisan migrate

参照:Migration Foreign Key Vs Eloquent Relationships in Laravel 强调一下,Eloquent关系和Migration必须同时创建,但是外键约束视情况而定。 Laravel Relationship - Foreign key delete

2.模型关联:

User.php中添加:

  1 public function votes()
  2 {
  3     return $this->belongsToMany(Answer::class, ‘votes‘)->withTimestamps();
  4 }
  5 

Answer.php中添加:

  1 public function users()
  2 {
  3     return $this->belongsToMany(User::class, ‘votes‘)->withTimestamps();
  4 }
  5 

注意 表名由于不是laravel默认的格式,所以要自己设置表名

  1 <?php
  2
  3 namespace App;
  4
  5 use App\Models\Question;
  6 use Illuminate\Database\Eloquent\Model;
  7 use Illuminate\Database\Eloquent\SoftDeletes;
  8
  9 class Answer extends Model
 10 {
 11     #region 支持软删除添加
 12     use SoftDeletes;
 13     protected $dates = [‘deleted_at‘];
 14
 15     #endregion
 16
 17     protected $fillable = [‘user_id‘, ‘question_id‘, ‘content‘];
 18
 19     /** 一个回答只有一个回答主人
 20      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 21      */
 22     public function user()
 23     {
 24         return $this->belongsTo(User::class);
 25     }
 26
 27     /** 一个回答只针对一个问题
 28      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
 29      */
 30     public function question()
 31     {
 32         return $this->belongsTo(Question::class);
 33     }
 34
 35     /**
 36      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 37      */
 38     public function userVotes()
 39     {
 40         return $this->belongsToMany(User::class, ‘votes‘)->withTimestamps();
 41     }
 42 }
 43
 44 

Answer.php

最好在User.php中添加上voteAnswer方法,更方便:

  1 public function voteAnswer($answer_id)
  2 {
  3     return $this->votes()->toggle($answer_id);
  4 }
  5 

  1 <?php
  2
  3 namespace App;
  4
  5 use App\Models\Question;
  6 use Illuminate\Contracts\Auth\MustVerifyEmail;
  7 use Illuminate\Database\Eloquent\SoftDeletes;
  8 use Illuminate\Foundation\Auth\User as Authenticatable;
  9 use Illuminate\Notifications\Notifiable;
 10
 11 class User extends Authenticatable implements MustVerifyEmail
 12 {
 13     use Notifiable;
 14     #region 支持软删除
 15     use SoftDeletes;
 16     protected $dates = [‘deleted_at‘];
 17     #endregion
 18     /**
 19      * The attributes that are mass assignable.
 20      *
 21      * @var array
 22      */
 23     protected $fillable = [
 24         ‘name‘, ‘email‘, ‘password‘, ‘avatar‘, ‘activation_token‘, ‘api_token‘
 25     ];
 26
 27     /**
 28      * The attributes that should be hidden for arrays.
 29      *
 30      * @var array
 31      */
 32     protected $hidden = [
 33         ‘password‘, ‘remember_token‘,
 34     ];
 35
 36     /**
 37      * The attributes that should be cast to native types.
 38      *
 39      * @var array
 40      */
 41     protected $casts = [
 42         ‘email_verified_at‘ => ‘datetime‘,
 43     ];
 44
 45
 46     /**添加用户模型和问题模型的模型关联
 47      * @return \Illuminate\Database\Eloquent\Relations\HasMany
 48      */
 49     public function questions()
 50     {
 51         return $this->hasMany(Question::class);
 52     }
 53
 54
 55     /** 添加用户模型和回答模型的模型关联 一个用户可以有多个回答
 56      * @return \Illuminate\Database\Eloquent\Relations\HasMany
 57      */
 58     public function answers()
 59     {
 60         return $this->hasMany(Answer::class);
 61     }
 62
 63
 64     public function followQuestions()
 65     {
 66         //默认表名 可以不设置后面三个参数,自定义表名需要设置
 67         return $this->belongsToMany(Question::class, ‘users_questions‘, ‘question_id‘, ‘user_id‘)->withTimestamps();
 68     }
 69
 70
 71     /** 用户的粉丝
 72      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 73      */
 74     public function followers()
 75     {
 76
 77         return $this->belongsToMany
 78         (
 79             self::class,
 80             ‘followers‘,
 81             ‘user_id‘, //foreignPivotKey:当前模型在中间表的字段(当前模型类的外键) //【当前模型是leader】的外键id
 82             ‘follower_id‘//relatedPivotKey:另一模型在中间表的字段(另一模型类的外键)
 83         )->withTimestamps();
 84     }
 85
 86
 87     /** 用户关注的作者
 88      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 89      */
 90     public function followings()
 91     {
 92         return $this->belongsToMany
 93         (
 94             self::class,
 95             ‘followers‘,
 96             ‘follower_id‘,//foreignPivotKey:当前模型在中间表的字段(当前模型类的外键) //【当前模型是粉丝】的外键id
 97             ‘user_id‘//relatedPivotKey:另一模型在中间表的字段(另一模型类的外键)
 98         )
 99             ->withTimestamps();
100     }
101
102
103     /**
104      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
105      */
106     public function votes()
107     {
108         return $this->belongsToMany(Answer::class, ‘votes‘)->withTimestamps();
109     }
110
111
112     /**
113      * @param $answer_id
114      * @return array
115      */
116     public function voteAnswer($answer_id)
117     {
118         return $this->votes()->toggle($answer_id);
119     }
120 }
121
122 

User.php

3.视图层面:直接使用vue组件:

  1 <template>
  2     <button :class="classObject"
  3             @click="up"
  4             v-text="text">
  5     </button>
  6 </template>
  7
  8 <script>
  9     export default {
 10         props: [‘answer‘],
 11         name: "UserVoteButton",
 12         data() {
 13             return {
 14                 voteable: true,
 15             }
 16         },
 17         computed: {
 18             text() {
 19                 return this.voteable ? "点赞" : "取消赞";
 20             },
 21             classObject() {
 22                 return this.voteable ? "btn btn-sm btn-secondary" : "btn btn-sm btn-danger";
 23             },
 24         },
 25         mounted: function () {
 26             let currentObj = this;
 27             axios.post(‘/api/answers/vote/stats‘, {‘answer‘: this.answer})
 28                 .then(function (response) {
 29                     currentObj.voteable = response.data.voteable;
 30                 })
 31                 .catch(function (e) {
 32                     console.log(e);
 33                 });
 34         },
 35         methods: {
 36             up() {
 37                 let currentObj = this;
 38                 axios.post(‘/api/answers/vote/up‘, {‘answer‘: this.answer})
 39                     .then(function (response) {
 40                             currentObj.voteable = response.data.voteable;
 41                         }
 42                     )
 43                     .catch(function (e) {
 44                         console.log(e);
 45                     });
 46             },
 47             //暂时不写踩的
 48             down() {
 49                 let currentObj = this;
 50                 axios.post(‘/api/answers/vote/down‘, {‘answer‘: this.answer})
 51                     .then(function (response) {
 52                             currentObj.voteable = response.data.voteable;
 53                         }
 54                     )
 55                     .catch(function (e) {
 56                         console.log(e);
 57                     });
 58             },
 59         }
 60     }
 61 </script>
 62
 63 <style scoped>
 64
 65 </style>
 66
 67 

UserVoteButton

  1 /**
  2  * First we will load all of this project‘s JavaScript dependencies which
  3  * includes Vue and other libraries. It is a great starting point when
  4  * building robust, powerful web applications using Vue and Laravel.
  5  */
  6
  7 require(‘./bootstrap‘);
  8 require(‘../../vendor/select2/select2/dist/js/select2.js‘);
  9 // 将views/vendor/ueditor/assets.blade.php中的引用换到本处
 10 require(‘../../public/vendor/ueditor/ueditor.config.js‘);
 11 require(‘../../public/vendor/ueditor/ueditor.all.js‘);
 12
 13 window.Vue = require(‘vue‘);
 14
 15 /**
 16  * The following block of code may be used to automatically register your
 17  * Vue components. It will recursively scan this directory for the Vue
 18  * components and automatically register them with their "basename".
 19  *
 20  * Eg. ./components/ExampleComponent.vue -> <example-component></example-component>
 21  */
 22
 23 // const files = require.context(‘./‘, true, /\.vue$/i)
 24 // files.keys().map(key => Vue.component(key.split(‘/‘).pop().split(‘.‘)[0], files(key).default))
 25
 26 // Vue.component(‘example-component‘, require(‘./components/ExampleComponent.vue‘).default);
 27 Vue.component(‘question-follow-button‘, require(‘./components/QuestionFollowButton‘).default);
 28 Vue.component(‘user-follow-button‘, require(‘./components/UserFollowButton‘).default);
 29 Vue.component(‘user-vote-button‘, require(‘./components/UserVoteButton‘).default);
 30 /**
 31  * Next, we will create a fresh Vue application instance and attach it to
 32  * the page. Then, you may begin adding components to this application
 33  * or customize the JavaScript scaffolding to fit your unique needs.
 34  */
 35
 36 const app = new Vue({
 37     el: ‘#app‘,
 38 });
 39
 40 

app.js

  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‘,[‘userable‘=>$answer])
 72                             <span class="float-right text text-info text-center">
 73                                 {{ $answer->updated_at->diffForHumans() }}</span>
 74                             @if(auth()->check())
 75                                 <user-vote-button answer="{{ $answer->id }}" class="float-right"></user-vote-button>
 76                             @endif
 77                         </div>
 78
 79                         <div class="card-body">
 80                             {!!  $answer->content  !!}
 81                         </div>
 82                     </div>
 83
 84                 @empty
 85
 86                 @endforelse
 87             </div>
 88
 89             <div class="col-md-3">
 90                 <div class="card">
 91                     <div class="card-header">
 92                         <h2> {{ $question->followers_count }}</h2>
 93                         <span>关注者</span>
 94                     </div>
 95                     <div class="card-body">
 96                         <question-follow-button question="{{$question->id}}"id}}">
 97                         </question-follow-button>
 98                     </div>
 99                 </div>
100
101                 <div class="card mt-4">
102                     <div class="card-header">
103                         <h2> 提问者 </h2>
104                     </div>
105                     <div class="card-body">
106                         @include(‘users._small_icon‘,[‘userable‘=>$question])
107                     </div>
108                     @include(‘users._user_stats‘)
109                 </div>
110             </div>
111
112
113         </div>
114     </div>
115 @endsection
116 @section(‘footer-js‘)
117     @include(‘questions._footer_js‘)
118 @endsection
119
120 

show.blade.php

api.php:

  1 <?php
  2
  3 use Illuminate\Http\Request;
  4
  5 /*
  6 |--------------------------------------------------------------------------
  7 | API Routes
  8 |--------------------------------------------------------------------------
  9 |
 10 | Here is where you can register API routes for your application. These
 11 | routes are loaded by the RouteServiceProvider within a group which
 12 | is assigned the "api" middleware group. Enjoy building your API!
 13 |
 14 */
 15
 16 Route::middleware(‘auth:api‘)->get(‘/user‘, function (Request $request) {
 17     return $request->user();
 18 });
 19
 20 Route::middleware(‘api‘)->get(‘/topics‘, function (Request $request) {
 21     $query = $request->query(‘q‘);
 22     return \App\Topic::query()->where(‘name‘, ‘like‘, ‘%‘ . $query . ‘%‘)->get();
 23 });
 24 #region 问题关注
 25 //加载页面时取关注状态
 26 Route::middleware(‘auth:api‘)->post(‘/questions/follow/stats‘, ‘[email protected]‘);
 27 //执行关注/取关操作
 28 Route::middleware(‘auth:api‘)->post(‘/questions/follow‘, ‘[email protected]‘);
 29 #endregion
 30
 31 #region 用户关注
 32 //加载页面时取关注状态
 33 Route::middleware(‘auth:api‘)->post(‘/users/follow/stats‘, ‘[email protected]‘);
 34 //执行关注/取关操作
 35 Route::middleware(‘auth:api‘)->post(‘/users/follow‘, ‘[email protected]‘);
 36
 37 #endregion
 38
 39
 40 #region
 41 //加载页面时取赞状态
 42 Route::middleware(‘auth:api‘)->post(‘/answers/vote/stats‘, ‘[email protected]‘);
 43 //执行赞/取消赞操作
 44 Route::middleware(‘auth:api‘)->post(‘/answers/vote/up‘, ‘[email protected]‘);
 45 #endregion
 46
 47 

api.php

4.控制器:

  1 php artisan make:controller VoteController

VoteController.php:

  1 <?php
  2
  3 namespace App\Http\Controllers;
  4
  5 use App\Answer;
  6 use Illuminate\Http\Request;
  7
  8 class VoteController extends Controller
  9 {
 10     //
 11     public function __construct()
 12     {
 13         $this->middleware(‘auth‘);
 14     }
 15
 16
 17     public function getVoteStats(Request $request)
 18     {
 19         $answer = Answer::find($request->get(‘answer‘));
 20
 21         $user = auth()->user();
 22
 23         //是否可以点赞
 24         return response()->json(
 25             [
 26                 ‘voteable‘ => !($user->votes->contains(‘id‘, $answer->id))
 27             ]
 28         );
 29     }
 30
 31     public function voteUpThroughApi(Request $request)
 32     {
 33         $answer = Answer::find($request->get(‘answer‘));
 34
 35         $user = auth()->user();
 36
 37         $user->voteAnswer($answer->id);
 38
 39         //是否可以点赞
 40         return response()->json(
 41             [
 42                 ‘voteable‘ => !($user->votes->contains(‘id‘, $answer->id))
 43             ]
 44         );
 45     }
 46 }
 47
 48 

VoteController.php

5.如果要对赞进行计数:

  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‘,[‘userable‘=>$answer])
 72                             <span class="float-right text text-info text-center">
 73                                 {{ $answer->updated_at->diffForHumans() }}</span>
 74                             @if(auth()->check())
 75                                 <user-vote-button answer="{{ $answer->id }}" vote_count="{{ $answer->userVotes->count() }}" class="float-right"></user-vote-button>
 76                             @endif
 77                         </div>
 78
 79                         <div class="card-body">
 80                             {!!  $answer->content  !!}
 81                         </div>
 82                     </div>
 83
 84                 @empty
 85
 86                 @endforelse
 87             </div>
 88
 89             <div class="col-md-3">
 90                 <div class="card">
 91                     <div class="card-header">
 92                         <h2> {{ $question->followers_count }}</h2>
 93                         <span>关注者</span>
 94                     </div>
 95                     <div class="card-body">
 96                         <question-follow-button question="{{$question->id}}"id}}">
 97                         </question-follow-button>
 98                     </div>
 99                 </div>
100
101                 <div class="card mt-4">
102                     <div class="card-header">
103                         <h2> 提问者 </h2>
104                     </div>
105                     <div class="card-body">
106                         @include(‘users._small_icon‘,[‘userable‘=>$question])
107                     </div>
108                     @include(‘users._user_stats‘)
109                 </div>
110             </div>
111
112
113         </div>
114     </div>
115 @endsection
116 @section(‘footer-js‘)
117     @include(‘questions._footer_js‘)
118 @endsection
119
120 

show.blade.php

  1 <template>
  2     <button :class="classObject"
  3             @click="up"
  4             v-text="text">
  5     </button>
  6 </template>
  7
  8 <script>
  9     export default {
 10         props: [‘answer‘, ‘vote_count‘],
 11         name: "UserVoteButton",
 12         data() {
 13             return {
 14                 voteable: true,
 15                 vote_count: this.vote_count,
 16             }
 17         },
 18         computed: {
 19             text() {
 20                 return this.vote_count;
 21             },
 22             classObject() {
 23                 return this.voteable ? "btn btn-sm btn-secondary" : "btn btn-sm btn-danger";
 24             },
 25         },
 26         mounted: function () {
 27             let currentObj = this;
 28             axios.post(‘/api/answers/vote/stats‘, {‘answer‘: this.answer})
 29                 .then(function (response) {
 30                     currentObj.voteable = response.data.voteable;
 31                     currentObjvote_count = response.data.vote_count;
 32                 })
 33                 .catch(function (e) {
 34                     console.log(e);
 35                 });
 36         },
 37         methods: {
 38             up() {
 39                 let currentObj = this;
 40                 axios.post(‘/api/answers/vote/up‘, {‘answer‘: this.answer})
 41                     .then(function (response) {
 42                             currentObj.voteable = response.data.voteable;
 43                             currentObj.vote_count = response.data.vote_count;
 44                         }
 45                     )
 46                     .catch(function (e) {
 47                         console.log(e);
 48                     });
 49             },
 50             //暂时不写踩的
 51             down() {
 52                 let currentObj = this;
 53                 axios.post(‘/api/answers/vote/down‘, {‘answer‘: this.answer})
 54                     .then(function (response) {
 55                             currentObj.voteable = response.data.voteable;
 56                         }
 57                     )
 58                     .catch(function (e) {
 59                         console.log(e);
 60                     });
 61             },
 62         }
 63     }
 64 </script>
 65
 66 <style scoped>
 67
 68 </style>
 69
 70 

UserVoteButton.vue

  1 <?php
  2
  3 namespace App\Http\Controllers;
  4
  5 use App\Answer;
  6 use Illuminate\Http\Request;
  7
  8 class VoteController extends Controller
  9 {
 10     //
 11     public function __construct()
 12     {
 13         $this->middleware(‘auth‘);
 14     }
 15
 16
 17     public function getVoteStats(Request $request)
 18     {
 19         $answer = Answer::find($request->get(‘answer‘));
 20
 21         $user = auth()->user();
 22
 23         //是否可以点赞
 24         return response()->json(
 25             [
 26                 ‘voteable‘ => !($user->votes->contains(‘id‘, $answer->id)),
 27                 ‘vote_count‘ => $answer->userVotes->count(),
 28             ]
 29         );
 30     }
 31
 32     public function voteUpThroughApi(Request $request)
 33     {
 34         $answer = Answer::find($request->get(‘answer‘));
 35
 36         $user = auth()->user();
 37
 38         $user->voteAnswer($answer->id);
 39
 40         //是否可以点赞
 41         return response()->json(
 42             [
 43                 ‘voteable‘ => !($user->votes->contains(‘id‘, $answer->id)),
 44                 ‘vote_count‘ => $answer->userVotes->count(),
 45             ]
 46         );
 47     }
 48 }
 49
 50 

VoteController.php

原文地址:https://www.cnblogs.com/dzkjz/p/12399221.html

时间: 2024-10-20 11:58:30

Laravel Vuejs 实战:开发知乎 (27)对答案进行点赞的相关文章

Laravel Vuejs 实战:开发知乎 (33)自定义helper方法

参考: laravel 中添加自定义辅助函数helpers.php laravel自定义公共函数的引入怎么使用 Laravel增加自定义助手函数 Laravel 添加自定义全局函数 laravel 添加帮助类在helper 辅助函数 Laravel 目录结构:自定义函数的存放位置 创建 app/Http/helpers.php文件 修改 compose.json文件 1 "autoload": { 2 "classmap": [ 3 "database/s

Laravel Vuejs 实战:开发知乎 (37)私信标为已读

1.自定义MessageCollection类: 1 <?php 2 3 namespace App; 4 5 use Illuminate\Database\Eloquent\Collection; 6 7 class MessageCollection extends Collection 8 { 9 public function markAsRead() 10 { 11 $this->each(function ($message) { 12 $message->markAsRe

Laravel 教程 - Web 开发实战入门 ( Laravel 5.5 )购买链接

? Laravel 教程 - Web 开发实战入门 ( Laravel 5.5 )购买链接: 推荐给你高品质的实战课程 https://laravel-china.org/courses?rf=15818 ? ? 文章来源:刘俊涛的博客 欢迎关注,有问题一起学习欢迎留言.评论. 原文地址:https://www.cnblogs.com/lovebing/p/9578193.html

100套最适合自学的实战开发教程视频(程序员都在学)

BAT大咖助力 全面升级Android面试 BAT大牛亲授 基于ElasticSearch的搜房网实战 从天气项目看Spring Cloud微服务治理 Java企业级电商项目架构演进之路  Tomcat集群与Redis分布式 Java深入微服务原理改造房产销售平台 SSM到Spring Boot-从零开发校园商铺平台 Java Spring Boot企业微信点餐系统 Java秒杀系统方案优化-高性能高并发实战 Spring Boot技术栈博客企业前后端 Java SSM快速开发仿慕课网在线教育平

《H5+移动应用实战开发》已出版

<H5+移动应用实战开发>终于出版了,最近在忙着Vue和Webpack相关的前端书籍写稿.本书面向的读者为:从后端转前端,或零基础开始学习移动端开发的人.前后端完全分离的开发方式越来越成为一种趋势,下一本书,将是专业前端书籍,是关于Vue在实际工作中的单页应用开发,涉及到Vue全家桶以及webpack相关技术. 京东:https://item.jd.com/12521607.html 当当:http://product.dangdang.com/27864696.html 天猫:H5+移动应用

Android软硬整合设计与框架揭秘: HAL&amp;Framework &amp;Native Service &amp;App&amp;HTML5架构设计与实战开发

掌握Android从底层开发到框架整合技术到上层App开发及HTML5的全部技术: 一次彻底的Android架构.思想和实战技术的洗礼: 彻底掌握Andorid HAL.Android Runtime.Android Framework.Android Native Service.Android Binder.Android App.Android Testing.HTML5技术的源泉和精髓等核心技术,不仅仅是技术和代码本身,更重要的是背后的设计思想和商业哲学. 一.课程特色 l  贯通And

基于微博数据应用的HBase实战开发_HBase视频教程

基于微博数据应用的HBase实战开发 课程观看地址:http://www.xuetuwuyou.com/course/150 课程出自学途无忧网:http://www.xuetuwuyou.com 一.课程用到的软件 1.centos6.7 2.apache-tomcat-7.0.47 3.solr-5.5 4.zookeeper 3.4.6 5.eclipse-jee-neon-R-win32-x86_64  6.jdk1.7_49 7.HBase1.2.2 8.Ganglia3.7.2 9.

升级版:深入浅出Hadoop实战开发(云存储、MapReduce、HBase实战微博、Hive应用、Storm应用)

      Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS.HDFS有着高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上.而且它提供高传输率(high throughput)来访问应用程序的数据,适合那些有着超大数据集(large data set)的应用程序

【课程分享】深入浅出微信公众平台实战开发(微网站、LBS云、Api接口调用、服务号高级接口)

深入浅出微信公众平台实战开发(微网站.LBS云.Api接口调用.服务号高级接口) 课程下载地址:链接:http://pan.baidu.com/share/link?shareid=2214724072&uk=3611155194 密码:glvc 一.本课程是怎么样的一门课程(全面介绍) 1.1.课程的背景 微信公众平台的火热程度已经不用多言,无论是个人还是企业,政府还是商家,都已经开始搭建微信公众平台,微信的作用已经被各界人士认可.微信公众平台的技术需求市场缺口巨大. 1.2.课程内容简介 本