相关链接
- 视频教程 https://www.youtube.com/watch?v=XTDNs4TB_lE&list=PL38wFHH4qYZXH8Gb7PIbmyjdsWdEJLImp
- 文档
- TailwindCSS: https://tailwindcss.com/docs/guides/laravel
- Alpine.js: https://www.alpinejs.cn/
常用关键标签
blade指令
安装
运行
辅助函数
blade指令
@csrf
form表单里面使用
@yield('main')
占位符
@extends('layout')
继承模板
@section('main')<h1>hello</h1>@endsection
向对应的布局(占位)注入内容
@auth <br> @endauth
用户登录
@guest <h1>guess</h1> @endguest
游客(匿名用户)
@method('delete')
form表单里面设置请求类型
artisan 常用命令
# 查看所有的命令
php artisan
# 额外参数 查看命令帮助
-h
# 启动项目
php artisan serve
# 创建组件
php artisan make:component
# 创建匿名组件
--view
# 删除所有的表
php artisan db:wipe
# 执行迁移文件
php artisan migrate
# 覆盖模式
php artisan migrate:fresh
# 回滚
php artisan migrate:rollback
# 创建控制器
php artisan make:controller AuthController
# 为模型生成迁移、种子器、工厂、策略、资源控制器和表单请求类
php artisan make:model Post -a
# 创建api类型控制器
php artisan make:model Post -a --api
# 数据工厂
php artisan db:seed
# 创建邮件
php artisan make:mail 邮件名称
# 创建事件
php artisan make:event UserSubscribed
# 创建侦听器
php artisan make:listener SendSubcriberEmail
# 创建文件夹快捷访问路径 一般公共文件这么操作
php artisan storage:link
# 生成策略文件
php artisan make:policy UserPolicy
校验参数
required
min:1
max:1
重复性校验 注册的时候查看密码是否相同
confirmed
例如 表单字段 password 和 password_confirmation
unique:users
判断表单跟数据库中的字段是否重复
nullable
可以为空
file
文件
mimes:png,jpg,webp
文件类型
方法
use Illuminate\Support\Facades\Auth;
// 登录 对象
Auth::login($user);
// 登录 用户名和密码 和 记住登录
Auth::attempt($fileds, $request->remember)
// 跳转
redirect()->route('home');
// 跳转到根目录 默认为跳转到根 可以填写对应的数据
redirect()->intended()
// 返回之前的页面 自定义错误信息
back()->withErrors(['failed' => '用户名或者密码错误']);
// 自定义成功信息
back()->with('success', '注册成功');
// 退出登录
public function logout(Request $request)
{
//注销用户
Auth::logout();
// 清除session
$request->session()->invalidate();
// 重新生成token
$request->session()->regenerateToken();
return redirect()->route('home');
}
// 获取时间差
$post->created_at->diffForHumans()
// 对文本进行操作 超过数量的显示省略号
Str::words($post->body, 15)
遇到的各种问题
Laravel中Carbon时间格式本地化(变成中文)
可以在 app/Providers/AppServiceProvider.php 的 boot() 方法中添加下面的代码来设置全局本地化:
public function boot()
{
\Carbon\Carbon::setLocale('zh');
}
设置好后
$article->created_at->diffForHumans();
知识点
安装
直接安装
composer create-project laravel/laravel example-app
全局安装 Laravel Installer 来创建新的 Laravel 项目
composer global require laravel/installer
laravel new example-app
使用 Laravel Installer 来创建新的 Laravel项目
laravel new
# 启动项目
php artisan serve
配置邮箱
.env 文件
MAIL_MAILER=smtp
MAIL_HOST=sandbox.smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=********
MAIL_PASSWORD=********
语言配置
设置中文配置: config/app.php
也可以直接在.env 文件中设置
# 时区
'timezone' => 'PRC',
# 验证提示中文
'locale' => 'zh_CN',
# faker中文
'faker_locale' => 'zh_CN',
中文验证
https://github.com/caouecs/Laravel-lang/tree/master/src/
https://packagist.org/packages/laravel-lang/lang#3.0.9/
https://laravel-lang.com/
直接安装
composer require laravel-lang/common --dev
# 添加
php artisan lang:add zh_CN
# 更新
php artisan lang:update
# 使用 publish 来发布语言包
php artisan lang:publish
vscode 扩展
三个vscode扩展
Laravel Blade Snippets
Laravel Extra Intellisense
Laravel Blade formatter
在 blade 文件中 是 @ 来触发快捷提示
使用vite来加速开发
在blade文件中引入vite
// 引入的资源 路径
@vite(['resources/css/app.css', 'resources/js/app.js'])
在项目根目录 使用
# 安装依赖
npm i
# 运行
npm run dev
这个时候修改blade文件后,前端可以主动刷新,不用再手动去刷新查看变化
安装 Tailwind CSS with Laravel
https://tailwindcss.com/docs/guides/laravel
vscode 中安装 Tailwind CSS IntelliSense
扩展
代码提示
# 安装
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
//在tailwind.config.js 修改配置 直接复制粘贴
content: [
"./resources/**/*.blade.php",
"./resources/**/*.js",
"./resources/**/*.vue",
],
/* 在 app.css 文件中 写入 全局的css文件中 */
@tailwind base;
@tailwind components;
@tailwind utilities;
组件
创建匿名组件
php artisan make:component --view
文件路径 会在 components 目录下生成对应的文件匿名组件
还可以自己创建 直接在 components 目录下创建文件
resources\views\components\layout.blade.php
使用匿名组件
用 x-
前缀+组件名
<x-layout></x-layout>
插槽
在组件中使用 {{$slot}}
调用组件 被包裹的内容就会填充到插槽中
<x-layout> 你好 </x-layout>
路由
<?php
use Illuminate\Support\Facades\Route;
// 默认使用的方式
Route::get('/', function () {
return view('posts.index');
})->name('home');
// 直接返回对应的视图
Route::view('/', 'posts.index')->name('home');
// name的作用
// 在视图中用{{route('home')}} 来方便的获取的对应url
{{route('home')}}
// 路由分组
Route::group(function(){});
// 路由重定向
Route::redirect('/', 'posts');
// 资源路由
Route::resource('posts', PostController::class);
表单校验
涉及的知识点
scrf
表单回填
表单校验
校验错误信息展示
// 控制器
<?php
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
// 注册用户
public function register(Request $request)
{
// 校验 返回的数据是通过校验的数据 不包含其他数据
$fileds = $request->validate([
// 'username' => ['required','max:255'],
'username' => 'required|max:255',
'email' => ['required', 'max:255', 'email', 'unique:users'],
'password' => ['required', 'min:3', 'confirmed']
], [
'username.required' => '用户名不能为空',
]);
// 注册 在对应的数据库中创建数据 返回当前创建的对象
$user = User::create($fileds);
// 登录 登录
Auth::login($user);
// 跳转 到首页
return redirect()->route('home');
}
// 用户登录
public function login(Request $request)
{
// 校验
$fileds = $request->validate([
// 'username' => ['required','max:255'],
'email' => ['required', 'max:255', 'email'],
'password' => ['required']
], [
'username.required' => '用户名不能为空',
]);
// dd($request);
// 登录 用户信息 和 记住登录
if (Auth::attempt($fileds, $request->remember)) {
// return redirect()->route('home');
// 默认跳转到根路径
return redirect()->intended();
} else {
// 返回之前的页面 自定义错误信息
return back()->withErrors(['failed' => '用户名或者密码错误']);
}
}
// 退出登录
public function logout(Request $request)
{
//注销用户
Auth::logout();
// 清除session
$request->session()->invalidate();
// 重新生成token
$request->session()->regenerateToken();
return redirect()->route('home');
}
}
<!-- 表单写法 -->
<form action="{{ route('register') }}" method="POST">
@csrf
{{-- 用户 --}}
<div class="mb-4">
<label for="username">用户名</label>
<input type="text" name="username" class="input @error('username') ring-red-600 @enderror"
value="{{ old('username') }}">
@error('username')
<p class="error">{{ $message }}</p>
@enderror
</div>
<div class="mb-4">
<label for="email">邮箱</label>
<input type="text" name="email" class="input @error('email') ring-red-600 @enderror"
value="{{ old('email') }}">
@error('email')
<p class="error">{{ $message }}</p>
@enderror
</div>
<div class="mb-4">
<label for="password">密码</label>
<input type="password" name="password" class="input @error('password') ring-red-600 @enderror"
value="{{ old('password') }}">
@error('password')
<p class="error">{{ $message }}</p>
@enderror
</div>
<div class="mb-4">
<label for="password_confirmation">确认密码</label>
<input type="password" name="password_confirmation"
class="input @error('password') ring-red-600 @enderror" value="{{ old('password_confirmation') }}">
</div>
<button class="btn mb-6">提交</button>
</form>
中间件
控制器中间件
对单独的控制器文件中使用控制器
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
class DashboardController extends Controller implements HasMiddleware
{
/**
* 获取应分配给控制器的中间件。
*/
public static function middleware(): array
{
return [
'auth',
new Middleware('log', only: ['index']), // 只对index方法使用
new Middleware('subscribed', except: ['store']), // 除了store方法使用
];
}
public function index()
{
return view('users.dashboard');
}
}
路由中间件
// 系统自带的中间件 只能登录的用户会通过
Route::->middleware('auth');
// 只有游客才能通过
Route::->middleware('guest');
// 单独使用
Route::view('/register', 'auth.register')->middleware('guest')->name('register');
// 使用中间件进行分组
Route::middleware('guest')->group(function () {
Route::view('/register', 'auth.register')->name('register');
});
模型
为模型生成迁移、种子器、工厂、策略、资源控制器和表单请求类
php artisan make:model Post -a
数据迁移
强制覆盖
php artisan migrate:fresh
执行迁移文件
php artisan migrate
回滚
php artisan rollback
// 迁移文件里面的代码
Schema::create('posts', function (Blueprint $table) {
$table->id();
// 外键 约束
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
$table->string('title');
$table->text('body');
$table->timestamps();
});
数据工厂 创建数据
命令
php artisan db:seed
<?php
// database\seeders\DatabaseSeeder.php
// 默认会执行这个路径的文件
namespace Database\Seeders;
use App\Models\Post;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
// 创建15个数据
Post::factory(15)->create();
}
}
修改对应的 factories 文件
<?php
// 文件路径
// database\factories\PostFactory.php
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory
{
public function definition(): array
{
return [
'user_id' => 1,
// 15个随机标题
'title' => fake()->sentence(10),
// 20g个随机段落
'body' => fake()->paragraph(20)
];
}
}
分页
控制器代码
// $posts = Post::orderBy('created_at', 'desc')->get();
// 以最新的去排序
$posts = Post::latest()->paginate(6);
return view('posts.index', ['posts' => $posts]);
显示页码数据
<div>
{{ $posts->links() }}
</div>
在 tailwind.config.js 文件中添加 pagination 文件路径 让tailwindcss 识别分页样式
/** @type {import('tailwindcss').Config} */
export default {
content: [
"vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php"
],
theme: {
extend: {},
},
plugins: [],
}
组件传参
flashMsg.blade.php
组件
@props(['msg', 'bg' => 'bg-green-500'])
// 两个参数 一个参数设置了默认zhi
<p class=" text-sm font-medium text-white p-2 rounded-md {{ $bg }}">
{{ $msg }}
</p>
调用 传递文本
@if (session('success'))
<div class="mb-2">
<x-flashMsg msg="{{ session('success') }}"></x-flashMsg>
</div>
@endif
传递对象
<x-flashMsg :msg="$msg"></x-flashMsg>
授权
文件路径
app\Policies\PostPolicy.php
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
class PostPolicy
{
// 创建对应的策略
public function modify(User $user, Post $post)
{
// 让当前用户的id和文章的user_id相等的通过
return $user->id === $post->user_id;
}
}
控制器
app\Http\Controllers\PostController.php
<?php
namespace App\Http\Controllers;
use App\Models\Post;
use Illuminate\Http\Request;
use Illuminate\Routing\Controllers\HasMiddleware;
use Illuminate\Routing\Controllers\Middleware;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
class PostController extends Controller implements HasMiddleware
{
/**
* 获取应分配给控制器的中间件。
*/
public static function middleware(): array
{
return [
// 使用的方法
// new Middleware('auth', only: ['store']),
// 排除auth中间件的方法
new Middleware('auth', except: ['index','show'])
];
}
/**
* Display a listing of the resource.
*/
public function index()
{
// $posts = Post::orderBy('created_at', 'desc')->get();
// 以最新的去排序
$posts = Post::latest()->paginate(6);
// dd($posts);
return view('posts.index', ['posts' => $posts]);
}
public function destroy(Post $post)
{
// 使用 PostPolicy 的策略
Gate::authorize('modify', $post);
// dd('ok');
// 删除一个post
$post->delete();
// 返回之前的页面
return back()->with(['delete' => '该文章已经删除成功']);
}
}
上传文件
表单文件设置 enctype="multipart/form-data" method="post"
<form action=" {{ route('posts.store') }} " method="post" enctype="multipart/form-data">
@csrf
<div class="mb-4">
<label for="image">上传图片</label>
<input type="file" name="image" id="image">
@error('image')
<p class="error">{{ $message }}</p>
@enderror
</div>
<button class="btn">提交按钮</button>
</form>
控制器文件
use Illuminate\Support\Facades\Storage;
//校验
$fields = $request->validate([
'title' => ['required', 'max:255'],
'body' => ['required'],
//可以为空 文件大小 文件后缀
'image' => ['nullable', 'file', 'max:1000', 'mimes:png,jpg,webp'],
]);
//如果文件存在 上传文件
$path = null;
if ($request->hasFile('image')) {
// 选择文件配置 默认的disk 设置文件路径
$path = Storage::disk('public')->put('posts_images', $request->image);
}
//保存数据
// Post::create(['user_id' => Auth::id(), ...$fields]);
// 通过获取当前用户的模型对象 获取到自定义的关联对象 通过关联数据来创建对象
Auth::user()->posts()->create([
'title' => $request->title,
'body' => $request->body,
'image' => $path
]);
// 跳转
更新文件
//如果文件存在 上传文件
$path = $post->image ?? null;
if ($request->hasFile('image')) {
// 如果之前有图片
if ($post->image) {
// 删除之前的图片
Storage::disk('public')->delete($post->image);
}
$path = Storage::disk('public')->put('posts_images', $request->image);
}
删除文件
// 删除图片
if ($post->image) {
Storage::disk('public')->delete($post->image);
}
邮件
配置
配置文件
MAIL_MAILER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=465
MAIL_USERNAME=邮箱
MAIL_PASSWORD=密码
MAIL_ENCRYPTION=null
// 发送的账号
MAIL_FROM_ADDRESS="12455@qq.com"
// 邮箱的标题
MAIL_FROM_NAME="${APP_NAME}"
创建文件
创建 邮件
php artisan make:mail 邮件名称
app\Mail\WelcomeMail.php
<?php
namespace App\Mail;
// use Faker\Provider\zh_CN\Address;
use App\Models\Post;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class WelcomeMail extends Mailable
{
use Queueable, SerializesModels;
// 在构造函数里面传递参数可以在 邮件类里面使用 在视图里面使用
public function __construct(public User $user, public Post $post)
{
//
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
// 这里可以
// 配置邮件标题
// 来自谁
// 发送给谁
// 可以添加内容
return new Envelope(
subject: '欢迎laravel11',
// from: new Address('779245779@qq.com', '张三'),
// // 回复
// replyTo: [
// new Address('645163229@qq.com', '张三'),
// ]
);
}
public function content(): Content
{
// 邮件的视图的路径
return new Content(
view: 'emails.welcome',
);
}
/**
* 添加附件内容
*
* $this->post 这个是通过构造函数传递过来的对象
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
*/
public function attachments(): array
{
return [
// 默认磁盘的路径配置
Attachment::fromStorage( $this->post->image),
// 选择对应的磁盘路径配置
Attachment::fromStorageDisk('public', $this->post->image),
];
}
}
视图文件
resources\views\emails\welcome.blade.php
<h1>欢迎 {{ $user->username }}</h1>
<div>
<div>你创建一个 {{ $post->body }}</div>
<p>{{ $post->body }}</p>
<!-- 使用这个方法去引用图片 -->
<img src="{{ $message->embed('storage/' . $post->image) }}" alt="">
</div>
发送邮件
控制器里面的写法
// 发送邮件
// to 发送给的邮箱
// WelcomeMail 创建的邮箱对象
// send(new WelcomeMail())
use App\Mail\WelcomeMail;
Mail::to(Auth::user())->send(new WelcomeMail(Auth::user(), $post));
邮箱认证功能
https://learnku.com/docs/laravel/11.x/verificationmd/16692
这里的文档有所有的流程
发送邮箱
use Illuminate\Auth\Events\Registered;
event(new Registered($user));
路由
Route::middleware('auth')->group(function () {
// 再次获取邮箱页面
Route::get('/email/verify', [AuthController::class, 'verifyNotice'])->name('verification.notice');
// 邮箱校验路由
// signed url 签名校验
Route::get('/email/verify/{id}/{hash}', [AuthController::class, 'verifyEmail'])->middleware('signed')->name('verification.verify');
// 再次获取 邮箱
//throttle 中间件避免多次提交表单
Route::post('/email/verification-notification', [AuthController::class, 'verifyHandler'])->middleware('throttle:6,1')->name('verification.send');
});
控制器
use Illuminate\Auth\Events\Registered;
use Illuminate\Foundation\Auth\EmailVerificationRequest;
// 注册用户
public function register(Request $request)
{
// 校验
$fileds = $request->validate([
// 'username' => ['required','max:255'],
'username' => 'required|max:255',
'email' => ['required', 'max:255', 'email', 'unique:users'],
'password' => ['required', 'min:3', 'confirmed']
], [
'username.required' => '用户名不能为空',
]);
// 注册
$user = User::create($fileds);
// 登录
Auth::login($user);
// 注册的时候发送邮件
// 发送邮件
event(new Registered($user));
// 跳转
return redirect()->intended();
}
public function verifyNotice()
{
return view('auth.verify-email');
}
// 邮箱校验通过
public function verifyEmail(EmailVerificationRequest $request)
{
$request->fulfill();
return redirect()->route('dashboard');
}
// 再次发送
public function verifyHandler(Request $request)
{
$request->user()->sendEmailVerificationNotification();
return back()->with('message', 'Verification link sent!');
}
再次获取页面视图
<x-layout>
<h1 class="mb-4">
请校验你的邮箱
</h1>
<p>没有获取到邮件</p>
<form action="{{ route('verification.send') }}" method="post">
@csrf
<button class="btn">再次发送</button>
</form>
</x-layout>
自定义发送的邮箱验证页面
这个文件路径
app\Providers\AppServiceProvider.php
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Notifications\Messages\MailMessage;
public function boot(): void
{
// ...
VerifyEmail::toMailUsing(function (object $notifiable, string $url) {
// return (new MailMessage)
// ->subject('Verify Email Address')
// ->line('Click the button below to verify your email address.')
// ->action('Verify Email Address', $url);
// 使用视图文件
return (new MailMessage)
->subject('验证邮箱地址')
->view('emails.verify-email', ['url' => $url]);
});
}
发送给邮箱的视图
<div>
<h1>点击下面的按钮校验你的邮箱</h1>
<a style="background: blue;color:white" href="{{ $url }}">校验邮箱</a>
</div>
事件 监听
# 创建事件
php artisan make:event UserSubscribed
# 创建侦听器
php artisan make:listener SendSubcriberEmail
# 创建侦听器
php artisan make:listener UpdateSubscribersTable
一个订阅的邮箱的功能
事件功能
app\Events\UserSubscribed.php
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class UserSubscribed
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*/
public function __construct(public User $user)
{
// dd('event called' . $name);
}
}
监听
app\Listeners\SendSubcriberEmail.php
<?php
namespace App\Listeners;
use App\Events\UserSubscribed;
use Illuminate\Support\Facades\Mail;
class SendSubcriberEmail
{
/**
* Create the event listener.
*/
public function __construct()
{
//
}
/**
* Handle the event.
*/
public function handle(UserSubscribed $event): void
{
// 简单发送文本
Mail::raw('欢迎订阅我的文本', function ($message) use ($event) {
$message->to($event->user->email);
$message->subject('欢迎订阅');
});
}
}
监听
app\Listeners\UpdateSubscribersTable.php
<?php
namespace App\Listeners;
use App\Events\UserSubscribed;
use Illuminate\Support\Facades\DB;
class UpdateSubscribersTable
{
public function __construct()
{
//
}
public function handle(UserSubscribed $event): void
{
DB::insert('insert into subscribers (email) values (?)', [$event->user->email]);
}
}
调用事件
use App\Events\UserSubscribed;
if ($request->subscribe) {
event(new UserSubscribed($user));
}
使用队列
运行
php artisan queue:work
配置文件使用redis
在监听文件中使用 配置使用 接口就行 如下
<?php
namespace App\Listeners;
use App\Events\OrderShipped;
use Illuminate\Contracts\Queue\ShouldQueue;
class SendShipmentNotification implements ShouldQueue
{
// ...
}
密码重置
https://learnku.com/docs/laravel/11.x/passwordsmd/16695#model-preparation
路由
// 进行分组
Route::middleware('guest')->group(function () {
// 重置密码
Route::view('/forgot-password', 'auth.forgot-password')->name('password.request');
// 发送重置密码邮件
Route::post('/forgot-password', [ResetPasswordController::class, 'passwordEmail'])->name('password.email');
// 校验
Route::get('/reset-password/{token}', [ResetPasswordController::class, 'passwordReset'])->name('password.reset');
// 更新
Route::post('/reset-password', [ResetPasswordController::class, 'passwordUpdate'])->name('password.update');
});
控制器 ResetPasswordController
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class ResetPasswordController extends Controller
{
// 发送邮件
public function passwordEmail(Request $request)
{
$request->validate(['email' => 'required|email']);
$status = Password::sendResetLink(
$request->only('email')
);
return $status === Password::RESET_LINK_SENT
? back()->with(['status' => __($status)])
: back()->withErrors(['email' => __($status)]);
}
// 返回密码重置页面
public function passwordReset(string $token)
{
return view('auth.reset-password', ['token' => $token]);
}
// 更新 post请求
public function passwordUpdate(Request $request)
{
$request->validate([
'token' => 'required',
'email' => 'required|email',
'password' => 'required|min:6|confirmed',
]);
$status = Password::reset(
$request->only('email', 'password', 'password_confirmation', 'token'),
function (User $user, string $password) {
$user->forceFill([
'password' => Hash::make($password)
])->setRememberToken(Str::random(60));
$user->save();
// 通知用户重置成功
event(new PasswordReset($user));
}
);
return $status === Password::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status))
: back()->withErrors(['email' => [__($status)]]);
}
}