主题
个人资料
上三节,已经完成了基本的用户认证等基本功能。现在开始,用户已经可以通过认证进入到系统内了。先不着急来创建文章的主功能。我们先来修改下个人信息。通过修改用户的个人信来学习下 Laravel 如果邮件发送这个功能。现在开始下面的流程。
用户登录系统后,有时候需要修改自己的资料。例如用户名,邮箱 密码之类的信息。首先来修改用户名
修改用户名
首先我们要创建用户相关的控制器,使用下面的命令
shell
php artisan make:controller UserController
在UserController
控制器中,添加 profile
方法
php
public function profile(Request $request)
{
return view('user.profile');
}
创建 profile 页面
shell
php artisan make:view user/profile
这个命令将会创建 resources\views\user\profile.blade.php
blade 模板文件。页面创建之后,继续需要添加路由,还是到 routes\web.php
添加下面的代码
php
## 用户
Route::controller(\App\Http\Controllers\UserController::class)->prefix('user')->group(function () {
Route::get('/profile', 'profile')->name('profile');
});
这次我们用更加简洁易懂的写法,这段代码的意思就是将 UserController
控制器进行分组。使用路由前缀 user
。例如下面的 /profile
路由,最终浏览器输入的是 user/profile
。这里还要注意 name
方法。具体可以看命名路由的文档。这个可以稍微解释下,可以理解为路由简短写法,但是一定要注意是唯一
的。然后再回到 profile.blade.php
页面,添加如下代码
php
<div>
<x-layout>
<x-slot:header>个人资料</x-slot:header>
<div class="text-xl">修改用户名</div>
<div class="w-full lg:w-1/2">
<!--这里 action 我们就是使用上面的所说的命名路由,但是是 POST 请求 -->
<form class="mt-10 space-y-6" action="{{ route('profile')}}" method="POST">
<label class="input input-bordered flex items-center gap-2 @error('email') input-error @enderror">
<input type="text" class="grow" placeholder="用户名" name="name" value="{{ auth()->user()->name }}" />
</label>
@error('name')
<div class="text-white alert alert-error">{{ $message }}</div>
@enderror
<div>
<button
type="submit"
class="flex justify-center px-3 py-1.5 w-full font-semibold text-white bg-indigo-600 rounded-md shadow-sm text-sm/6 hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
更 新
</button>
</div>
// 记得这里一定要加 csrf
@csrf
</form>
</div>
</x-layout>
</div>
修改路由
ok,我们的 profile 路由不光需要支持 Get 请求,还需要支持 Post 请求。我们再回到路由web.php
文件,使用 match
方法,让 /profile
路由支持两种请求方式
php
Route::controller(\App\Http\Controllers\UserController::class)->prefix('user')->group(function () {
Route::get('/profile', 'profile')->name('profile');
// 换成 match 方法
Route::match(['get', 'post'],'/profile', 'profile')->name('profile');
});
添加更新用户名逻辑
支持之后,我们需要回到 UserController
的 profile
方法了。需要在这个方法里面区别 Post 和 Get 请求,然后在 Post 逻辑里面处理更新用户名的逻辑
php
public function profile(Request $request)
{
// Post 请求处理
if ($request->isMethod('POST')) {
$request->validate([
'name' => 'required',
]);
$user = $request->user();
$user->name = $request->input('name');
$user->save();
return to_route('profile')->with('success', '用户名更新成功');
}
// Get 请求处理
return view('user.profile');
}
- 使用
$request->isMethod('Post')
判断是否是 Post 请求,也就是表单请求 - 直接使用
$request->validate
方式对表单字段进行验证,一般来说后端都是需要校验的,这个在之前的章节也有过说明 - 在 Laravel 框架中,你可以在
$request
中直接从user()
中获取认证过的用户,这里获取的用户是App\User
模型对象,所以你可以直接使用save
方法进行更新 - 我们上面提到的命名路由
profile
,to_route
就是类似redirect
重定向方法,后面紧接着的 with 方法可以闪存成功后的信息,会在后面给你展示是什么效果
这样的,用户名更新就已经可以了。然后再回到我们的 user\profile.blade.php
页面,我们在成功更新后,需要加一个提示信息。来看下如何处理的
php
<div>
<x-layout>
<x-slot:header>个人资料</x-slot:header>
<div class="text-xl">修改用户名</div>
<div class="w-full lg:w-1/2">
<form class="mt-10 space-y-6" action="{{ route('profile')}}" method="POST">
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<label class="input input-bordered flex items-center gap-2 @error('email') input-error @enderror">
<input type="text" class="grow" placeholder="用户名" name="name" value="{{ auth()->user()->name }}" />
</label>
@error('name')
<div class="text-white alert alert-error">{{ $message }}</div>
@enderror
<div>
<button
type="submit"
class="flex justify-center px-3 py-1.5 w-full font-semibold text-white bg-indigo-600 rounded-md shadow-sm text-sm/6 hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
更 新
</button>
</div>
@csrf
</form>
</div>
</x-layout>
</div>
我们刚才提到的 with
方法里面加了一个数组,是展示成功后的信息的。所以这个有什么作用呢?可以先看一下文档带闪存会话数据的重定向。 如文档所说,我们在重定向之后需要展示信息,现在代码中使用的是如下代码
php
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
在提交表单更新之后呢,告诉用户更新成功了。如下图所示
修改密码
修改密码其实是一样的逻辑,还是回到 UserController
控制器,然后添加修改密码的方法
添加 password 方法
php
public function password(Request $request)
{
return view('user.password');
}
添加修改密码页面
跟 profile
页面一样的操作,创建password.blade
文件
shell
php artisan make:view user/password
添加如下内容
php
<div>
<x-layout>
<x-slot:header>个人资料</x-slot:header>
<div class="text-xl">修改密码</div>
<div class="w-full lg:w-1/2">
<form class="mt-10 space-y-6" action="{{ route('password')}}" method="POST">
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<label class="input input-bordered flex items-center gap-2 @error('old_password') input-error @enderror">
<input type="text" class="grow" placeholder="原密码" name="old_password" value="" />
</label>
@error('old_password')
<div class="text-white alert alert-error">{{ $message }}</div>
@enderror
<label class="input input-bordered flex items-center gap-2 @error('new_password') input-error @enderror">
<input type="text" class="grow" placeholder="新密码" name="new_password" value="" />
</label>
@error('new_password')
<div class="text-white alert alert-error">{{ $message }}</div>
@enderror
<label class="input input-bordered flex items-center gap-2 @error('new_password_confirmation') input-error @enderror">
<input type="text" class="grow" placeholder="密码确认" name="new_password_confirmation" value="" />
</label>
@error('new_password_confirmation')
<div class="text-white alert alert-error">{{ $message }}</div>
@enderror
<div>
<button
type="submit"
class="flex justify-center px-3 py-1.5 w-full font-semibold text-white bg-indigo-600 rounded-md shadow-sm text-sm/6 hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
更 新
</button>
</div>
@csrf
</form>
</div>
</x-layout><!-- The best way to take care of the future is to take care of the present moment. - Thich Nhat Hanh -->
</div>
添加路由
这里跟上面的 profile
一样,直接支持 get 和 post 方法了,使用 match 方法
php
Route::controller(\App\Http\Controllers\UserController::class)->prefix('user')->group(function () {
Route::match(['get', 'post'],'/profile', 'profile')->name('profile');
// 添加 password 页面
Route::match(['get', 'post'],'/password', 'password')->name('password');
});
添加更新密码逻辑
更新密码的话,首先你需要知道原密码,然后要输入新密码,一般都需要做新密码确认。这样的逻辑,使用 Laravel 的验证器是很方便实现的。来看一下下面的逻辑
php
public function password(Request $request)
{
if ($request->isMethod('POST')) {
$request->validate([
'old_password' => 'required|current_password',
'new_password' => 'required|min:6|confirmed',
], [
'old_password.required' => '请输入当前密码',
'old_password.current_password' => '当前密码错误',
'new_password.required' => '请输入新密码',
'new_password.min' => '新密码长度至少6位',
'new_password.confirmed' => '两次输入的密码不一致',
]);
$user = $request->user();
$user->password = bcrypt($request->get('new_password'));
$user->save();
return to_route('password')->with(['success' => '更新密码成功']);
}
return view('user.password');
}
主要看一下 validate
验证,这里只要解释两个规则,一个是 current_password
和 confirmed
规则
- current_password 文档 验证当前登录用户的密码是否正确
- confirmed 文档 字段确认 例如
new_password
字段,如果需要使用confirmed
规则,需要在字段后面增加_confirmation
后缀。new_password
->new_password_confirmation
最后的效果如下
但是先别急,后面可以增加一个小的差异。这个取决于你的系统要求哈。就是修改密码之后呢是否需要重新登录。如果需要,我们要进行这样的操作
php
$user = $request->user();
$user->password = bcrypt($request->get('new_password'));
if ($user->save()) {
Auth::logout();
}
return redirect('/login')->with(['success' => '更新密码成功']);
在修改之后,我们进行退出操作,最后在重定向到 /login
页面,加一个更新修改密码的提示。但是目前的登录页面没有提示信息,所以需要添加一下,回到登录页面,添加如下的代码
php
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
<form class="space-y-6" action="/login" method="POST">
@if (session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<label class="input input-bordered flex items-center gap-2 @error('email') input-error @enderror">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor" class="w-4 h-4 opacity-70">
<path d="M2.5 3A1.5 1.5 0 0 0 1 4.5v.793c.026.009.051.02.076.032L7.674 8.51c.206.1.446.1.652 0l6.598-3.185A.755.755 0 0 1 15 5.293V4.5A1.5 1.5 0 0 0 13.5 3h-11Z" />
<path d="M15 6.954 8.978 9.86a2.25 2.25 0 0 1-1.956 0L1 6.954V11.5A1.5 1.5 0 0 0 2.5 13h11a1.5 1.5 0 0 0 1.5-1.5V6.954Z" />
</svg>
<input type="text" class="grow" placeholder="邮箱" name="email" value="{{ old('email') }}" />
</label>
...
</form>
效果如下,这样就很好了,当前做不做这样的操作呢,取决于系统定义。