[Laravel]表單驗證與返回

Kunyu
9 min readFeb 25, 2024
Photo by Mario Heller on Unsplash

表單是使用者與伺服器互動的一個重要功能,HTML所內建的表單就可以把使用者填寫的資料送給伺服器,下面這個簡單的範例會讓使用者填寫使用者名稱(username)、電子郵件(email)以及密碼(password),馬上要來感受第一個 Laravel 跟原生 PHP 相比好用功能 @csrf ,這是 Laravel 用來保護服務不要受到 csrf 攻擊的 blade 功能。

<form action="/register" method="POST" id="registration-form">
@csrf
<div class="form-group">
<label for="username-register" class="text-muted mb-1"><small>Username</small></label>
<input name="username" id="username-register" class="form-control" type="text" placeholder="Pick a username" autocomplete="off" />
</div>

<div class="form-group">
<label for="email-register" class="text-muted mb-1"><small>Email</small></label>
<input name="email" id="email-register" class="form-control" type="text" placeholder="you@example.com" autocomplete="off" />
</div>

<div class="form-group">
<label for="password-register" class="text-muted mb-1"><small>Password</small></label>
<input name="password" id="password-register" class="form-control" type="password" placeholder="Create a password" />
</div>

<div class="form-group">
<label for="password-register-confirm" class="text-muted mb-1"><small>Confirm Password</small></label>
<input name="password_confirmation" id="password-register-confirm" class="form-control" type="password" placeholder="Confirm password" />
</div>

<button type="submit" class="py-3 mt-4 btn btn-lg btn-success btn-block">Sign up for OurApp</button>
</form>

定義路由

路由(Route)是指定應用程式中特定 URL 請求應該由哪個程式處理的機制。在 Laravel 中,路由是在 routes 設定檔中定義的,用來將特定的 URL 對應到相應的控制器方法或閉包。在這段程式碼中,我們定義了一個 POST 方法的路由,當使用者發送 HTTP POST 請求到 /register 時,該請求將被導向到 UserController 的 register 方法進行處理。這樣,當使用者提交註冊表單時,其請求會被送至 UserController 的 register 方法進行處理,以執行註冊相關的邏輯。

Route::post('/register', [UserController::class, 'register']);

驗證表單與寫入資料庫

第二個好用功能,請求傳到 Controller 之後使用 validate 進行表單驗證,這個範例看起來很精簡,但其實 Laravel 背後做了不少事情,這邊我列出幾點來說明:

  1. validate 如果不通過,會自動導回上一頁,也就是表單輸入頁面。
  2. Rule::unique 可以檢查該值是否在資料表中是唯一的?
  3. 當驗證使用 confirmed,Laravel 就會去比對這個 name + _confirmation 的值,例如 password 就會比對 password_confirmation。
  4. 密碼並不能直接被存入資料庫,Laravel 提供了 bcrypt 函數進行雜湊處理,相比原生 PHP 更為簡潔。
  5. 最後直接使用 Model 把資料存入。
class UserController extends Controller
{
public function register(Request $request)
{
$incomingFields = $request->validate([
'username' => ['required', 'min:3', 'max:30', Rule::unique('users', 'username')],
'email' => ['required', 'email', Rule::unique('users', 'email')],
'password' => ['required', 'min:8', 'confirmed']
]);

$incomingFields['password'] = bcrypt($incomingFields['password']);

User::create($incomingFields);
return 'Hello from register function';
}
}

提升使用者體驗的 old() 與 @error

第三個好用功能,當驗證為不通過時,Laravel 會直接返回上一頁,但是使用者所填的資料會消失而且不知道發生了什麼事情,因此可以透過 old() 來保留使用者輸入的內容以及使用 @error 告訴使用者發生了什麼事情。

<form action="/register" method="POST" id="registration-form">
@csrf
<div class="form-group">
<label for="username-register" class="text-muted mb-1"><small>Username</small></label>
<input value="{{old('username')}}" name="username" id="username-register" class="form-control" type="text" placeholder="Pick a username" autocomplete="off" />
@error('username')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>

<div class="form-group">
<label for="email-register" class="text-muted mb-1"><small>Email</small></label>
<input value="{{old('email')}}" name="email" id="email-register" class="form-control" type="text" placeholder="you@example.com" autocomplete="off" />
@error('email')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>

<div class="form-group">
<label for="password-register" class="text-muted mb-1"><small>Password</small></label>
<input name="password" id="password-register" class="form-control" type="password" placeholder="Create a password" />
@error('password')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>

<div class="form-group">
<label for="password-register-confirm" class="text-muted mb-1"><small>Confirm Password</small></label>
<input name="password_confirmation" id="password-register-confirm" class="form-control" type="password" placeholder="Confirm password" />
@error('password_confirmation')
<p class="m-0 small alert alert-danger shadow-sm">{{$message}}</p>
@enderror
</div>

<button type="submit" class="py-3 mt-4 btn btn-lg btn-success btn-block">Sign up for OurApp</button>
</form>

--

--