表单处理 #
一、表单基础 #
1.1 创建表单 #
blade
<form method="POST" action="{{ route('users.store') }}">
@csrf
<div class="form-group">
<label for="name">姓名</label>
<input type="text" class="form-control" id="name" name="name" value="{{ old('name') }}">
</div>
<div class="form-group">
<label for="email">邮箱</label>
<input type="email" class="form-control" id="email" name="email" value="{{ old('email') }}">
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
1.2 CSRF保护 #
Laravel自动为所有表单提供CSRF保护:
blade
<form method="POST" action="/users">
@csrf
<!-- 表单字段 -->
</form>
1.3 表单方法伪造 #
blade
<form method="POST" action="/users/1">
@method('PUT')
@csrf
<!-- 表单字段 -->
</form>
<form method="POST" action="/users/1">
@method('DELETE')
@csrf
<!-- 表单字段 -->
</form>
二、获取输入 #
2.1 在控制器中获取输入 #
php
use Illuminate\Http\Request;
public function store(Request $request)
{
// 获取所有输入
$all = $request->all();
// 获取单个值
$name = $request->input('name');
// 获取带默认值
$name = $request->input('name', 'Guest');
// 检查是否存在
if ($request->has('name')) {
// 存在
}
// 检查是否有值
if ($request->filled('name')) {
// 有值(非空)
}
// 只获取指定字段
$data = $request->only(['name', 'email']);
// 排除指定字段
$data = $request->except(['_token']);
}
2.2 动态属性 #
php
// 通过动态属性获取
$name = $request->name;
$email = $request->email;
2.3 数组输入 #
blade
<input type="text" name="users[][name]">
<input type="text" name="users[][email]">
php
$users = $request->input('users');
// [['name' => 'John', 'email' => 'john@example.com']]
2.4 JSON输入 #
php
// 获取JSON输入
$data = $request->json()->all();
// 获取JSON字段
$name = $request->json('name');
三、文件上传 #
3.1 基本上传 #
blade
<form method="POST" action="/upload" enctype="multipart/form-data">
@csrf
<input type="file" name="avatar">
<button type="submit">上传</button>
</form>
php
public function upload(Request $request)
{
// 检查文件是否存在
if ($request->hasFile('avatar')) {
$file = $request->file('avatar');
// 检查是否有效
if ($file->isValid()) {
// 获取文件信息
$path = $file->path();
$extension = $file->extension();
$size = $file->getSize();
$mime = $file->getMimeType();
// 存储文件
$path = $file->store('avatars');
// 存储到指定磁盘
$path = $file->store('avatars', 's3');
// 自定义文件名
$path = $file->storeAs('avatars', 'custom_name.jpg');
}
}
}
3.2 文件验证 #
php
$validated = $request->validate([
'avatar' => 'required|image|max:1024', // 最大1MB
'document' => 'required|mimes:pdf,doc,docx|max:10240',
]);
3.3 文件信息 #
php
$file = $request->file('avatar');
// 原始文件名
$name = $file->getClientOriginalName();
// 原始扩展名
$extension = $file->getClientOriginalExtension();
// 文件大小(字节)
$size = $file->getSize();
// MIME类型
$mime = $file->getMimeType();
3.4 存储配置 #
php
// config/filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
],
],
3.5 访问上传文件 #
php
// 创建符号链接
php artisan storage:link
// 在视图中访问
<img src="{{ asset('storage/' . $user->avatar) }}">
// 或使用Storage门面
$url = Storage::url($user->avatar);
四、旧输入 #
4.1 获取旧输入 #
php
// 在控制器中
$name = $request->old('name');
// 在视图中
<input type="text" name="name" value="{{ old('name') }}">
4.2 闪存输入 #
php
// 闪存当前输入
$request->flash();
// 闪存部分输入
$request->flashOnly(['name', 'email']);
$request->flashExcept(['password']);
// 重定向时闪存
return redirect()->back()->withInput();
return redirect()->route('users.create')->withInput();
五、表单组件 #
5.1 创建表单组件 #
blade
<!-- resources/views/components/form/input.blade.php -->
@props(['label', 'name', 'type' => 'text', 'error'])
<div class="form-group">
<label for="{{ $name }}">{{ $label }}</label>
<input
type="{{ $type }}"
class="form-control {{ $error ? 'is-invalid' : '' }}"
id="{{ $name }}"
name="{{ $name }}"
value="{{ old($name, $value ?? '') }}"
{{ $attributes }}
>
@if($error)
<div class="invalid-feedback">{{ $error }}</div>
@endif
</div>
5.2 使用表单组件 #
blade
<x-form.input
name="email"
label="邮箱地址"
type="email"
:error="$errors->first('email')"
/>
六、多步表单 #
6.1 控制器处理 #
php
public function step1(Request $request)
{
$validated = $request->validate([
'name' => 'required',
'email' => 'required|email',
]);
session()->put('form.step1', $validated);
return redirect()->route('form.step2');
}
public function step2(Request $request)
{
$validated = $request->validate([
'address' => 'required',
'phone' => 'required',
]);
$data = array_merge(
session('form.step1', []),
$validated
);
// 保存数据
User::create($data);
session()->forget('form');
return redirect()->route('success');
}
七、表单安全 #
7.1 CSRF排除 #
php
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'api/*',
'webhook/*',
]);
})
7.2 XSS防护 #
blade
{{-- 自动转义 --}}
{{ $userInput }}
{{-- 原始输出(谨慎使用) --}}
{!! $trustedHtml !!}
7.3 SQL注入防护 #
php
// 使用参数绑定
$users = DB::select('SELECT * FROM users WHERE email = ?', [$email]);
// 使用Eloquent
$user = User::where('email', $email)->first();
八、最佳实践 #
8.1 使用表单请求验证 #
php
// 创建表单请求
php artisan make:request StoreUserRequest
// 使用
public function store(StoreUserRequest $request)
{
$user = User::create($request->validated());
return redirect()->route('users.show', $user);
}
8.2 表单组件化 #
blade
<!-- 使用组件 -->
<x-form.input name="name" label="姓名" required />
<x-form.select name="country" label="国家" :options="$countries" />
<x-form.textarea name="bio" label="简介" />
8.3 错误显示 #
blade
@if($errors->any())
<div class="alert alert-danger">
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
九、总结 #
9.1 核心要点 #
| 要点 | 说明 |
|---|---|
| @csrf | CSRF保护 |
| @method | 表单方法伪造 |
| $request->input() | 获取输入 |
| $request->file() | 获取文件 |
| old() | 获取旧输入 |
9.2 下一步 #
掌握了表单处理后,让我们继续学习 数据验证,了解Laravel强大的验证系统!
最后更新:2026-03-28