一、创建关注表
生成关注表
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
注意: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
注意:vendor.ueditor.assets 必须在 js 后面
@section('js')
@include('vendor.ueditor.assets')
新建文件:resources/assets/js/components/QuestionFollowButton.vue
执行 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;
})
}
}