Laravel Vuejs 实战:开发知乎 (45-47)用户设置

45节的重置密码省略:默认已经带得有。


因为用户个人信息等可能在后面会随时增加,比如增加一个字段存储用户的电话号码,增加一个字段存储用户的某社交账户的地址,

如果每次都用migration的方式,会比较不方便;建议采取如下方式。【如果这些信息需要排序,筛选,分类的情况另当别论,还是用字段的方式更快捷】

用户设置:

1.路由添加:

  1 #region
  2 
  3 Route::get('setting', 'SettingController@index')->name('setting.index');
  4 
  5 Route::post('setting', 'SettingController@store')->name('setting.store');
  6 #endregion
  7 
  8 

路由代码

  1 <?php
  2 
  3 /*
  4 |--------------------------------------------------------------------------
  5 | Web Routes
  6 |--------------------------------------------------------------------------
  7 |
  8 | Here is where you can register web routes for your application. These
  9 | routes are loaded by the RouteServiceProvider within a group which
 10 | contains the "web" middleware group. Now create something great!
 11 |
 12 */
 13 
 14 Route::get('/', function () {
 15     return view('welcome');
 16 });
 17 
 18 Auth::routes(['verify' => true]);
 19 
 20 Route::get('/home', 'HomeController@index')->name('home');
 21 
 22 Route::resource('questions', 'QuestionController');
 23 
 24 
 25 #region 回答路由CRUD
 26 
 27 //查看回答 以及 回答的form 都是在questions详细内容页面
 28 
 29 //提交回答
 30 Route::post('questions/{question}/answers', 'AnswerController@store')->name('answers.store');
 31 
 32 //更新回答
 33 
 34 
 35 //删除回答
 36 
 37 
 38 #endregion
 39 
 40 
 41 #region
 42 //用户关注 取消关注问题
 43 Route::get('questions/{question}/follow', 'QuestionController@follow')->name('questions.follow');
 44 #endregion
 45 
 46 
 47 #region
 48 
 49 //用户通知消息路由
 50 Route::get('/notifications', 'NotificationController@index')->name('notification.index');
 51 #endregion
 52 
 53 #region
 54 //用户查看短消息
 55 Route::get('/inbox', 'InboxController@index')->name('inbox.index');
 56 
 57 //展示用户间私信对话具体内容页
 58 Route::get('/inbox/{userId}', 'InboxController@show')->name('inbox.show');
 59 
 60 //用户回信息
 61 Route::post('/inbox/{userId}/send', 'InboxController@store')->name('inbox.store');
 62 #endregion
 63 
 64 
 65 #region
 66 //访问用户详细页面
 67 
 68 Route::get('/avatar', 'UserController@avatar')->name('users.avatar');
 69 
 70 Route::post('/avatar/upload', 'UserController@avatarStore');
 71 
 72 #endregion
 73 
 74 
 75 #region
 76 
 77 Route::get('setting', 'SettingController@index')->name('setting.index');
 78 
 79 Route::post('setting', 'SettingController@store')->name('setting.store');
 80 #endregion
 81 
 82 
web.php

2.执行:

  1 php artisan make:model Setting –c

控制器SettingController.php:

  1 <?php
  2 
  3 namespace App\Http\Controllers;
  4 
  5 use Illuminate\Http\Request;
  6 
  7 class SettingController extends Controller
  8 {
  9     //
 10     public function __construct()
 11     {
 12         $this->middleware('auth');
 13     }
 14 
 15     public function index()
 16     {
 17         $settings = auth()->user()->settings;
 18         return view('users.setting', compact('settings'));
 19     }
 20 
 21     public function store(Request $request)
 22     {
 23         $settings = auth()->user()->settings;
 24         if (!is_array($settings)) {
 25             $settings = [];
 26         }
 27         $settings = array_merge(
 28             $settings,
 29             array_only(
 30                 $request->all(),
 31                 [
 32                     'city',
 33                     'info'
 34                 ]
 35             )
 36         );
 37 
 38         auth()->user()->update(
 39             [
 40                 'settings' => $settings,
 41             ]
 42         );
 43         return redirect()->back()->with('success', '更新成功!');
 44     }
 45 
 46 }
 47 
 48 
SettingController.php

3.view视图:

setting.blade.php文件:

  1 @extends('layouts.app')
  2 
  3 @section('content')
  4 
  5     <div class="container">
  6         <div class="row">
  7             <div class="col-md-8 offset-2">
  8                 <div class="card">
  9                     <div class="card-header">
 10                         设置个人信息
 11                     </div>
 12                     <div class="card-body">
 13                         <form action="{{ route('setting.store') }}" method="post">
 14                             @csrf
 15                             <div class="form-group">
 16                                 <label for="city">现居城市</label>
 17                                 <input type="text" name="city" id="city" class="form-control"
 18                                        value="{{ $settings['city'] }}">
 19                                 @error('city') <span class="alert alert-danger">{{ $message }}</span>@enderror
 20                             </div>
 21 
 22 
 23                             <div class="form-group">
 24                                 <label for="info">个人简介</label>
 25                                 <textarea type="text" name="info" id="info"
 26                                           class="form-control">{{ $settings['info'] }}</textarea>
 27                                 @error('info') <span class="alert alert-danger">{{ $message }} </span>@enderror
 28                             </div>
 29 
 30 
 31                             <div class="form-group">
 32                                 <button type="submit" class="btn btn-success btn-block form-control">更新资料</button>
 33                             </div>
 34                         </form>
 35                     </div>
 36                 </div>
 37             </div>
 38         </div>
 39     </div>
 40 
 41 @endsection
 42 
 43 
setting.blade.php


settings字段采用的是: Eloquent: Mutators

参考:Eloquent: 修改器    有点类似WPF中的IValueConverter


4.User.php中的cast属性修改以及fillable属性修改:

批注 2020-03-05 001747

  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', 'settings',
 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         'settings' => 'array',
 44     ];
 45 
 46 
 47     /**添加用户模型和问题模型的模型关联
 48      * @return \Illuminate\Database\Eloquent\Relations\HasMany
 49      */
 50     public function questions()
 51     {
 52         return $this->hasMany(Question::class);
 53     }
 54 
 55 
 56     /** 添加用户模型和回答模型的模型关联 一个用户可以有多个回答
 57      * @return \Illuminate\Database\Eloquent\Relations\HasMany
 58      */
 59     public function answers()
 60     {
 61         return $this->hasMany(Answer::class);
 62     }
 63 
 64 
 65     public function followQuestions()
 66     {
 67         //默认表名 可以不设置后面三个参数,自定义表名需要设置
 68         return $this->belongsToMany(Question::class, 'users_questions', 'question_id', 'user_id')->withTimestamps();
 69     }
 70 
 71 
 72     /** 用户的粉丝
 73      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 74      */
 75     public function followers()
 76     {
 77 
 78         return $this->belongsToMany
 79         (
 80             self::class,
 81             'followers',
 82             'user_id', //foreignPivotKey:当前模型在中间表的字段(当前模型类的外键) //【当前模型是leader】的外键id
 83             'follower_id'//relatedPivotKey:另一模型在中间表的字段(另一模型类的外键)
 84         )->withTimestamps();
 85     }
 86 
 87 
 88     /** 用户关注的作者
 89      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 90      */
 91     public function followings()
 92     {
 93         return $this->belongsToMany
 94         (
 95             self::class,
 96             'followers',
 97             'follower_id',//foreignPivotKey:当前模型在中间表的字段(当前模型类的外键) //【当前模型是粉丝】的外键id
 98             'user_id'//relatedPivotKey:另一模型在中间表的字段(另一模型类的外键)
 99         )
100             ->withTimestamps();
101     }
102 
103 
104     /**
105      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
106      */
107     public function votes()
108     {
109         return $this->belongsToMany(Answer::class, 'votes')->withTimestamps();
110     }
111 
112 
113     /**
114      * @param $answer_id
115      * @return array
116      */
117     public function voteAnswer($answer_id)
118     {
119         return $this->votes()->toggle($answer_id);
120     }
121 
122 
123     public function messages()
124     {
125         return $this->hasMany(Message::class, 'to_user_id');
126     }
127 
128     public function comments()
129     {
130         return $this->hasMany(Comment::class);
131     }
132 
133 }
134 
135 
User.php

5.RegisterController.php修改:

批注 2020-03-05 001650

  1 <?php
  2 
  3 namespace App\Http\Controllers\Auth;
  4 
  5 use App\Http\Controllers\Controller;
  6 use App\Providers\RouteServiceProvider;
  7 use App\User;
  8 use Illuminate\Foundation\Auth\RegistersUsers;
  9 use Illuminate\Support\Facades\Hash;
 10 use Illuminate\Support\Facades\Validator;
 11 
 12 class RegisterController extends Controller
 13 {
 14     /*
 15     |--------------------------------------------------------------------------
 16     | Register Controller
 17     |--------------------------------------------------------------------------
 18     |
 19     | This controller handles the registration of new users as well as their
 20     | validation and creation. By default this controller uses a trait to
 21     | provide this functionality without requiring any additional code.
 22     |
 23     */
 24 
 25     use RegistersUsers;
 26 
 27     /**
 28      * Where to redirect users after registration.
 29      *
 30      * @var string
 31      */
 32     protected $redirectTo = RouteServiceProvider::HOME;
 33 
 34     /**
 35      * Create a new controller instance.
 36      *
 37      * @return void
 38      */
 39     public function __construct()
 40     {
 41         $this->middleware('guest');
 42     }
 43 
 44     /**
 45      * Get a validator for an incoming registration request.
 46      *
 47      * @param array $data
 48      * @return \Illuminate\Contracts\Validation\Validator
 49      */
 50     protected function validator(array $data)
 51     {
 52         return Validator::make($data, [
 53             'name' => ['required', 'string', 'max:255'],
 54             'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
 55             'password' => ['required', 'string', 'min:8', 'confirmed'],
 56         ]);
 57     }
 58 
 59     /**
 60      * Create a new user instance after a valid registration.
 61      *
 62      * @param array $data
 63      * @return \App\User
 64      */
 65     protected function create(array $data)
 66     {
 67         return User::create([
 68             'name' => $data['name'],
 69             'email' => $data['email'],
 70             'avatar' => '/image/avatars/default.png',
 71             //这里其实不需要再设置activation_token的值,也不需要再在验证后设置activated=1 采用Laravel提供的新功能验证用户邮箱即可 默认带一个email_verified_at字段,且更加完善具有过期时间戳和签名
 72             'activation_token' => str_random(40),//通过composer require laravel/helpers安装扩展包
 73             'password' => Hash::make($data['password']),
 74             'api_token' => str_random(64),
 75             'settings' => ['city' => '', 'info' => ''],
 76         ]);
 77     }
 78 }
 79 
 80 
RegisterController.php

效果图:

批注 2020-03-05 003252

6.重构SettingController的store方法:



新建一个Setting.php文件:

代码:

  1 <?php
  2 
  3 namespace App;
  4 
  5 
  6 class Setting
  7 {
  8     protected $allowedAttribute = [
  9         'city',
 10         'info'
 11     ];
 12     /**
 13      * @var User
 14      */
 15     private $user;
 16 
 17     public function __construct(User $user)
 18     {
 19 
 20         $this->user = $user;
 21     }
 22 
 23     //
 24     public function merge(array $attributes)
 25     {
 26         $settings = $this->user->settings;
 27 
 28         if (!is_array($settings)) {
 29             $settings = [];
 30         }
 31 
 32         $settings = array_merge(
 33             $settings,
 34             array_only(
 35                 $attributes,
 36                 $this->allowedAttribute
 37             )
 38         );
 39 
 40         $this->user->update([
 41             'settings' => $settings,
 42         ]);
 43     }
 44 }
 45 
 46 
Setting.php

User.php中添加一个方法:

  1 public function settings()
  2 {
  3     return new Setting($this);
  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', 'settings',
 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         'settings' => 'array',
 44     ];
 45 
 46 
 47     /**添加用户模型和问题模型的模型关联
 48      * @return \Illuminate\Database\Eloquent\Relations\HasMany
 49      */
 50     public function questions()
 51     {
 52         return $this->hasMany(Question::class);
 53     }
 54 
 55 
 56     /** 添加用户模型和回答模型的模型关联 一个用户可以有多个回答
 57      * @return \Illuminate\Database\Eloquent\Relations\HasMany
 58      */
 59     public function answers()
 60     {
 61         return $this->hasMany(Answer::class);
 62     }
 63 
 64 
 65     public function followQuestions()
 66     {
 67         //默认表名 可以不设置后面三个参数,自定义表名需要设置
 68         return $this->belongsToMany(Question::class, 'users_questions', 'question_id', 'user_id')->withTimestamps();
 69     }
 70 
 71 
 72     /** 用户的粉丝
 73      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 74      */
 75     public function followers()
 76     {
 77 
 78         return $this->belongsToMany
 79         (
 80             self::class,
 81             'followers',
 82             'user_id', //foreignPivotKey:当前模型在中间表的字段(当前模型类的外键) //【当前模型是leader】的外键id
 83             'follower_id'//relatedPivotKey:另一模型在中间表的字段(另一模型类的外键)
 84         )->withTimestamps();
 85     }
 86 
 87 
 88     /** 用户关注的作者
 89      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 90      */
 91     public function followings()
 92     {
 93         return $this->belongsToMany
 94         (
 95             self::class,
 96             'followers',
 97             'follower_id',//foreignPivotKey:当前模型在中间表的字段(当前模型类的外键) //【当前模型是粉丝】的外键id
 98             'user_id'//relatedPivotKey:另一模型在中间表的字段(另一模型类的外键)
 99         )
100             ->withTimestamps();
101     }
102 
103 
104     /**
105      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
106      */
107     public function votes()
108     {
109         return $this->belongsToMany(Answer::class, 'votes')->withTimestamps();
110     }
111 
112 
113     /**
114      * @param $answer_id
115      * @return array
116      */
117     public function voteAnswer($answer_id)
118     {
119         return $this->votes()->toggle($answer_id);
120     }
121 
122 
123     public function messages()
124     {
125         return $this->hasMany(Message::class, 'to_user_id');
126     }
127 
128     public function comments()
129     {
130         return $this->hasMany(Comment::class);
131     }
132 
133     public function settings()
134     {
135         return new Setting($this);
136     }
137 }
138 
139 
User.php
SettingController.php:

  1 <?php
  2 
  3 namespace App\Http\Controllers;
  4 
  5 use Illuminate\Http\Request;
  6 
  7 class SettingController extends Controller
  8 {
  9     //
 10     public function __construct()
 11     {
 12         $this->middleware('auth');
 13     }
 14 
 15     public function index()
 16     {
 17         $settings = auth()->user()->settings;
 18         return view('users.setting', compact('settings'));
 19     }
 20 
 21     public function store(Request $request)
 22     {
 23 //        $settings = auth()->user()->settings;
 24 //        if (!is_array($settings)) {
 25 //            $settings = [];
 26 //        }
 27 //        $settings = array_merge(
 28 //            $settings,
 29 //            array_only(
 30 //                $request->all(),
 31 //                [
 32 //                    'city',
 33 //                    'info'
 34 //                ]
 35 //            )
 36 //        );
 37 //
 38 //        auth()->user()->update(
 39 //            [
 40 //                'settings' => $settings,
 41 //            ]
 42 //        );
 43 
 44         auth()->user()->settings()->merge($request->all());
 45 
 46 
 47         return redirect()->back()->with('success', '更新成功!');
 48     }
 49 }
 50 
 51 
SettingController.php

批注 2020-03-05 004616

最后:

https://github.com/dzkjz/zhihuapp

posted @ 2020-03-04 22:20  dzkjz  阅读(293)  评论(0编辑  收藏  举报