Skip to content

个人资料

上三节,已经完成了基本的用户认证等基本功能。现在开始,用户已经可以通过认证进入到系统内了。先不着急来创建文章的主功能。我们先来修改下个人信息。通过修改用户的个人信来学习下 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 w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-semibold text-white shadow-sm 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'); 
});

添加更新用户名逻辑

支持之后,我们需要回到 UserControllerprofile 方法了。需要在这个方法里面区别 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 w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-semibold text-white shadow-sm 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

在提交表单更新之后呢,告诉用户更新成功了。如下图所示 Laravel入门教程-个人资料更新

修改密码

修改密码其实是一样的逻辑,还是回到 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 w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-semibold text-white shadow-sm 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_passwordconfirmed 规则

  • current_password 文档 验证当前登录用户的密码是否正确
  • confirmed 文档 字段确认 例如 new_password 字段,如果需要使用 confirmed 规则,需要在字段后面增加 _confirmation 后缀。new_password -> new_password_confirmation

最后的效果如下

Laravel入门教程-个人密码更新

但是先别急,后面可以增加一个小的差异。这个取决于你的系统要求哈。就是修改密码之后呢是否需要重新登录。如果需要,我们要进行这样的操作

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>

效果如下,这样就很好了,当前做不做这样的操作呢,取决于系统定义。 Laravel入门教程-个人密码更新

修改邮箱

在修改邮箱之前,我们需要一些提前准备工作。我们将使用邮箱服务发送验证码来验证邮箱的正确性。首先需要配置邮箱服务,我们选择使用 QQ 邮箱服务。使用 QQ 邮箱服务,需要获取授权码,按照下面的步骤来配置 QQ 邮箱服务。

获取 QQ 邮箱授权码

Laravel入门教程-修改邮箱

  • 找到“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV 服务”部分。

Laravel入门教程-修改邮箱

  • 开启“POP3/SMTP 服务”或“IMAP/SMTP 服务”。
  • 根据提示完成验证(通常需要发送短信),然后会生成一个授权码,记下来。

Laravel 入门教程-修改邮箱

配置邮箱服务

获取授权码之后,配置 Mail 邮箱服务

php
MAIL_MAILER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=465
MAIL_USERNAME="你的@qq.com"
MAIL_PASSWORD="上面配置后的授权码"
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS="你的@qq.com"
MAIL_FROM_NAME="${APP_NAME}"

创建邮件类

使用下面的命令生成邮件类

shell
php artisan make:mail SendEmailCode

这会在 app/Mail 目录下生成一个 SendEmailCode.php 文件。在创建一个 email 模板

shell
php artisan make:view emails/sendCode

找到 resources/views/emails/sendCode.blade.php 邮件模板,然后作如下修改,这里就简单一点

php
<!DOCTYPE html>
<html>
<head>
    <title>邮箱更改</title>
</head>
<body>
    <h1>Hello</h1>
    <p>这是一封来自 {{ config('app.name')}} 的邮箱更改邮件,验证码 : {{ $code }}</p>
</body>
</html>

再回到 UserController 控制器,添加下面两个方法

php
// 邮箱更改方法
public function email(Request $request)
{
    // 等后面添加
    return view('user.email');
}

// 发送邮箱更改验证码
public function sendEmailCode(Request $request)
{
    // 首先这里要判断邮箱是否会和其他冲突
    // 使用 unique 规则,验证提交的邮箱是否在 users 表里唯一
    $request->validate([
        'email' => 'required|email|unique:users,email,' . Auth::id(),
    ]);

    $newEmail = $request->get('email');

    // 判断提交的邮箱是否和当前邮箱不同,不同才会发送
    if ($newEmail != $request->user()->email) {
        Mail::to($request->get('email'))->send(new SendEmailCode(Str::random(4)));

        return to_route('email')->with(['success' => '发送邮件成功']);
    }

    return to_route('email');
}

添加邮箱验证路由

这里就不赘述了,还是到 routes/web.php 进行

php
Route::controller(\App\Http\Controllers\UserController::class)->prefix('user')->group(function () {
    # 邮件
    Route::match(['get', 'post'],'/email', 'email')->name('email'); 
    Route::post('sendEmailCode', 'sendEmailCode')->name('sendEmailCode'); 
});

创建修改邮箱页面

shell
php artisan make:view user/email

然后找到 resources/views/user/email.blade.php 模板,添加如下代码