laravel5.3开发知乎-第9章-关注问题 laravel5.3开发知乎-第9章-关注问题

2023-07-12

一、创建关注表

生成关注表

php artisan make:migration create_user_question_table --create=user_question

修改生成的 create_user_question_table.php

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

执行数据迁移

php artisan migrate

二、关注流程

生成关注模型

php artisan make:model Follow

修改 app/Follow.php

protected $table = 'user_question';

protected $fillable = ['user_id', 'question_id'];

修改 app/User.php

public function follows()
{
   return $this->belongsToMany(Question::class, 'user_question')->withTimestamps();
}

public function followsThis($question)
{
   return $this->follows()->toggle($question);
}

public function followed($question)
{
   return !! $this->follows()->where('question_id', $question)->count();
}

修改 app/Question.php

public function follows()
{
   return $this->belongsToMany(User::class, 'user_question')->withTimestamps();
}

注册路由

Route::get('question/{question}/follow', 'QuestionFollowController@follow');

新增 app/Support/helpers.php

if(!function_exists('user')){
   function user($driver = null){
       if($driver){
           return app('auth')->guard($driver)->user();
       }
       return app('auth')->user();
   }
}

修改 composer.json 的 autoload 属性

"autoload": {
   "files": [
       "app/Support/helpers.php"
   ],
   "classmap": [
       "database"
   ],
   "psr-4": {
       "App\\": "app/"
   }
},

执行 autoload

composer dump-autoload

生成控制器

php artisan make:controller QuestionFollowController

修改 app/Http/Controllers/QuestionFollowController.php

namespace App\Http\Controllers;

use App\Repositories\QuestionRepository;
use Auth;

class QuestionFollowController extends Controller
{
   protected $questionRepository;

   public function __construct(QuestionRepository $questionRepository)
   {
       $this->middleware('auth');
       $this->questionRepository = $questionRepository;
   }

   public function follow($question)
   {
       Auth::user()->followsThis($question);
       return back();
   }

   public function follower()
   {
       $followed = user('api')->followed(request('question'));
       return response()->json(['followed' => $followed]);
   }

   public function followThisQuestion()
   {
       $followed = user('api')->followsThis(request('question'));
       $question = $this->questionRepository->byId(request('question'));
       if(count($followed['detached']) > 0){
           $followed = false;
           $question->decrement('followers_count');
       }else{
           $followed = true;
           $question->increment('followers_count');
       }
       return response()->json(['followed' => $followed]);
   }
}

修改 resources/views/questions/show.blade.php

https://file.lulublog.cn/images/3/2023/07/LJ3l3O39JTZJAPjopVQjjjjE99APO4.jpg

注意:vendor.ueditor.assets 必须在 js 后面

@section('js')
@include('vendor.ueditor.assets')

修改 resources/assets/css/style.css

.question-follow {
   text-align: center;
}

执行 gulp

gulp

三、vue 组件

修改 routes/api.php

Route::post('/questions/follower', 'QuestionFollowController@follower')->middleware('auth:api');
Route::post('/questions/follow', 'QuestionFollowController@followThisQuestion')->middleware('auth:api');

修改 resources/views/questions/show.blade.php

https://file.lulublog.cn/images/3/2023/07/ztnxr3484s0tz8LOG0xt3N4lT3144J.jpg

注意:vendor.ueditor.assets 必须在 js 后面

@section('js')
@include('vendor.ueditor.assets')

新建文件:resources/assets/js/components/QuestionFollowButton.vue

https://file.lulublog.cn/images/3/2023/07/X34EUz7NwWw4MNnTvgAPh0zSNp3SI3.jpg

执行 gulp

gulp

四、Authorization

4.1、用户新增 api_token

生产数据迁移文件

php artisan make:migration add_api_token_to_users --table=users

修改生成的 add_api_token_to_users.php

public function up()
{
   Schema::table('users', function (Blueprint $table) {
       $table->string('api_token',64)->unique();
   });
}

public function down()
{
   Schema::table('users', function (Blueprint $table) {
       $table->dropColumn(['api_token']);
   });
}

执行数据迁移

php artisan migrate

进入数据迁移

php artisan tinker

为用户生成 api_token

str_random(60)

将生成的 api_token 保存于当前登录的用户表数据中

修改 app/Http/Controllers/Auth/RegisterController.php

protected function create(array $data)
{
   $user = User::create([
       'name' => $data['name'],
       'email' => $data['email'],
       'avatar' => '/images/avatars/default.png',
       'confirmation_token' => str_random(40),
       'password' => bcrypt($data['password']),
       'api_token' => str_random(60),
   ]);
   $this->sendVerifyEmailTo($user);
   return $user;
}

4.2、传递 api_token

修改 resources/assets/js/bootstrap.js

Vue.http.interceptors.push((request, next) => {
   request.headers.set('X-CSRF-TOKEN', Laravel.csrfToken);
   request.headers.set('Authorization', Laravel.apiToken);

   next();
});

修改 resources/views/layouts/app.blade.php

window.Laravel = <?php echo json_encode([
   'csrfToken' => csrf_token(),
]); ?>;
Laravel.apiToken = "{{ Auth::check() ? 'Bearer '.Auth::user()->api_token : ''}}"

4.3、注册路由

修改 resources/views/questions/show.blade.php 的 question-follow-button,将 user 去除

question-follow-button question="{{$question->id}}"

修改 resource/assets/js/components/QuestionFollowButton.vue,将 user 去除

props:['question'],

mounted() {
 this.$http.post('/api/questions/follower',{'question':this.question}).then(response => {
   this.followed = response.data.followed;
 })
},

methods: {
 follow() {
   this.$http.post('/api/questions/follow',{'question':this.question}).then(response => {
     this.followed = response.data.followed;
   })
 }
}
阅读 446