zoukankan      html  css  js  c++  java
  • Laravel Vuejs 实战:开发知乎 (23)用户关注之组件化开发

    开发vue的时候最好在开始的时候执行:

      1 npm install && npm run watch-poll

    这样每次编辑了vue都会后台自动生成一下,方便查看效果。

    1.生成一个控制器:

    php artisan make:controller FollowerController

    代码:

      1 <?php
      2 
      3 namespace AppHttpControllers;
      4 
      5 use AppUser;
      6 use IlluminateHttpRequest;
      7 
      8 class FollowerController extends Controller
      9 {
     10     //
     11     public function __construct()
     12     {
     13         $this->middleware('auth')
     14             ->except(
     15                 [
     16                     'getFollowStats',
     17                     'followThroughApi',
     18                 ]
     19             );
     20     }
     21 
     22 
     23     public function getFollowStats(Request $request)
     24     {
     25         //解析出用户
     26         $user = User::find($request->get('user'));
     27         //解析出当前登录用户
     28         $currentUser = auth()->user();
     29         //返回能否关注的状态 [follow是FollowPolicy中的follow方法,FollowPolicy已经在AuthServiceProvider中注册]
     30         return response()->json(['followable' => $currentUser->can('follow', $user),
     31             'self' => $user->id === $currentUser->id,]);
     32     }
     33 
     34 
     35     public function followThroughApi(Request $request)
     36     {
     37         //解析出用户
     38         $user = User::find($request->get('user'));
     39 
     40         //解析出当前登录用户
     41         $currentUser = auth()->user();
     42 
     43         //执行关注/取关操作 [不能关注自己]
     44         if ($user->id !== $currentUser->id) {
     45             $currentUser->followings()->toggle($user->id);
     46         }
     47 
     48         //返回新能否关注的状态 [follow是FollowPolicy中的follow方法,FollowPolicy已经在AuthServiceProvider中注册]
     49         return response()->json(
     50             [
     51                 'followable' => $currentUser->can('follow', $user),
     52                 'self' => $user->id === $currentUser->id,
     53             ]
     54         );
     55     }
     56 }
     57 
     58 
    FollowerController.php

    1.2 添加一个授权策略

    php artisan make:policy FollowPolicy

      1 <?php
      2 
      3 namespace AppPolicies;
      4 
      5 use AppUser;
      6 use IlluminateAuthAccessHandlesAuthorization;
      7 
      8 class FollowPolicy
      9 {
     10     use HandlesAuthorization;
     11 
     12     /**
     13      * Create a new policy instance.
     14      *
     15      * @return void
     16      */
     17     public function __construct()
     18     {
     19         //
     20     }
     21 
     22     public function follow(User $currentUser, User $user)
     23     {
     24         //用户不能关注自己,也不能关注已经关注的用户
     25         return $currentUser->id !== $user->id && !($currentUser->followings->contains('id', $user->id));
     26     }
     27 }
     28 
     29 
    FollowPolicy.php

    Lightning记得添加到AuthServiceProvider的 $policies中

    代码:

      1 <?php
      2 
      3 namespace AppProviders;
      4 
      5 use AppModelsQuestion;
      6 use AppPoliciesFollowPolicy;
      7 use AppPoliciesQuestionPolicy;
      8 use AppUser;
      9 use IlluminateFoundationSupportProvidersAuthServiceProvider as ServiceProvider;
     10 use IlluminateSupportFacadesGate;
     11 
     12 class AuthServiceProvider extends ServiceProvider
     13 {
     14     /**
     15      * The policy mappings for the application.
     16      *
     17      * @var array
     18      */
     19     protected $policies = [
     20         // 'AppModel' => 'AppPoliciesModelPolicy',
     21         //添加授权映射关系
     22         Question::class => QuestionPolicy::class,
     23         User::class => FollowPolicy::class,
     24     ];
     25 
     26     /**
     27      * Register any authentication / authorization services.
     28      *
     29      * @return void
     30      */
     31     public function boot()
     32     {
     33         $this->registerPolicies();
     34 
     35         //
     36     }
     37 }
     38 
     39 
    AuthServiceProvider.php

    2.添加api route:

      1 
      2 #region 用户关注
      3 //加载页面时取关注状态
      4 Route::middleware('auth:api')->post('/users/follow/stats', 'FollowerController@getFollowStats');
      5 //执行关注/取关操作
      6 Route::middleware('auth:api')->post('/users/follow', 'FollowerController@followThroughApi');
      7 
      8 #endregion
      9 
     10 
      1 <?php
      2 
      3 use IlluminateHttpRequest;
      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 AppTopic::query()->where('name', 'like', '%' . $query . '%')->get();
     23 });
     24 #region 问题关注
     25 //加载页面时取关注状态
     26 Route::middleware('auth:api')->post('/questions/follow/stats', 'QuestionController@getFollowStats');
     27 //执行关注/取关操作
     28 Route::middleware('auth:api')->post('/questions/follow', 'QuestionController@followThroughApi');
     29 #endregion
     30 
     31 #region 用户关注
     32 //加载页面时取关注状态
     33 Route::middleware('auth:api')->post('/users/follow/stats', 'FollowerController@getFollowStats');
     34 //执行关注/取关操作
     35 Route::middleware('auth:api')->post('/users/follow', 'FollowerController@followThroughApi');
     36 
     37 #endregion
     38 
     39 
    api.php

    3.添加用户关注按钮vue组件:

      1 <template>
      2     <button :class="classObject"
      3             @click="follow"
      4             v-text="text">
      5     </button>
      6 </template>
      7 
      8 <script>
      9     export default {
     10         props: ['user'],
     11         name: "UserFollowButton",
     12         data() {
     13             return {
     14                 followable: true,
     15                 self: true,
     16             }
     17         },
     18         computed: {
     19             text() {
     20                 return this.followable ? "关注" : "取关";
     21             },
     22             classObject() {
     23                 if (this.self) {
     24                     return "d-none"
     25                 }
     26                 return this.followable ? "btn btn-sm btn-secondary" : "btn btn-sm btn-danger";
     27             },
     28         },
     29         mounted: function () {
     30             let currentObj = this;
     31             axios.post('/api/users/follow/stats', {'user': this.user})
     32                 .then(function (response) {
     33                     currentObj.followable = response.data.followable;
     34                     currentObj.self = response.data.self;
     35                 })
     36                 .catch(function (e) {
     37                     console.log(e);
     38                 });
     39         },
     40         methods: {
     41             follow() {
     42                 let currentObj = this;
     43                 axios.post('/api/users/follow', {'user': this.user})
     44                     .then(function (response) {
     45                             currentObj.followable = response.data.followable;
     46                             currentObj.self = response.data.self;
     47                         }
     48                     )
     49                     .catch(function (e) {
     50                         console.log(e);
     51                     });
     52             },
     53         }
     54     }
     55 </script>
     56 
     57 <style scoped>
     58 
     59 </style>
     60 
     61 
    UserFollowButton.vue
      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 
    _user_stats.blade.php

    补充:之前User模型中 外键设置理解错误了Crying face,参考:

    数据库(外键及其约束理解)

    Laravel学习记录--Model

    修改后Thumbs up

      1 <?php
      2 
      3 namespace App;
      4 
      5 use AppModelsQuestion;
      6 use IlluminateContractsAuthMustVerifyEmail;
      7 use IlluminateDatabaseEloquentSoftDeletes;
      8 use IlluminateFoundationAuthUser as Authenticatable;
      9 use IlluminateNotificationsNotifiable;
     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 IlluminateDatabaseEloquentRelationsHasMany
     48      */
     49     public function questions()
     50     {
     51         return $this->hasMany(Question::class);
     52     }
     53 
     54 
     55     /** 添加用户模型和回答模型的模型关联 一个用户可以有多个回答
     56      * @return IlluminateDatabaseEloquentRelationsHasMany
     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 IlluminateDatabaseEloquentRelationsBelongsToMany
     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 IlluminateDatabaseEloquentRelationsBelongsToMany
     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 
    User.php
  • 相关阅读:
    DICOM:DICOM3.0网络通信协议
    Maven使用—拷贝Maven依赖jar包到指定目录
    Spring Boot使用JavaMailSender发送邮件
    SpringBoot配置Email发送功能
    MariaDB 安装与启动 过程记录
    ESXi与Linux主机配置syslog日志上传远程服务器
    Linux--忘记MySQL密码的解决方法和输入mysqld_safe --skip-grant-tables &后无法进入MySQL的解决方法
    centos killall安装
    centos安装lspci工具
    oracle创建job和删除job
  • 原文地址:https://www.cnblogs.com/dzkjz/p/12396091.html
Copyright © 2011-2022 走看看