Validation trong Laravel

Validation trong Laravel là hoạt động xác định sự chính xác ý nghĩa của dữ liệu đầu vào từ các form.

Khi thực hiện validate, bạn đưa ra các quy tắc để kiểm tra dữ liệu có đúng không. Ví dụ: điểm phải là số từ 1 đến 10, email phải đúng dạng, cmnd phải có 9 hoặc 10 ký số …

Laravel hỗ trợ nhiều cách để kiểm tra dữ liệu đầu vào và hiện các thông báo lỗi cho user…

Mục lục

Đặt vấn đề xử lý validattion

Giả sử có 2 routes và controller như sau

use App\Http\Controllers\SvController;
Route::get("/sv",[SvController::class,'sv']);
Route::post("/sv",[SvController::class,'sv_store'])->name('sv_store');

Trong SvController.php có 2 action như sau:

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class SvController extends Controller {
   public function sv(){
     return view("formnhapsv");
   }
   function sv_store(Request $request){  }
}

View formnhapsv như sau:

<link rel="stylesheet"  href= "https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css">
<form method="post" class="p-3 border border-primary col-6 m-auto"
  action="{{route('sv_store')}}" > @csrf 
<div class="mb-3"> 
  <label>Họ tên</label><input value="{{old('ht')}}" class="form-control" name="ht">
</div>
<div class="mb-3">
  <label>Tuổi</label><input value="{{old('tuoi')}}" class="form-control" name="tuoi">
</div>
<div class="mb-3">
  <label>Ngàysinh</label><input value="{{old('ns')}}" class="form-control" name="ns">
</div>
<div class="mb-3">
  <label>CMND</label><input value="{{old('cmnd')}}" class="form-control" name="cmnd">
</div>
<div class="mb-3">
  <label>Email</label> <input value="{{old('em')}}" class="form-control" name="em">
</div>
<div class="mb-3">
  <button type="submit" class="btn btn-primary w-25">Xử lý</button>
</div>
</form>

Giờ thì chạy project và xem thử route   http://localhost:8000/sv

Vấn đề: Trước khi lưu vào db, cần kiểm tra dữ liệu trong form xem có đúng các quy tắc:

  • Họ tên: phải nhập, dài 2 đến 30 ký tự
  • Tuổi: phải nhập số nguyên từ 16 đến 80
  • Ngày sinh: phải nhập kiểu dd/mm/yyyy
  • CMND: phải nhập từ 9 đến 10 ký số
  • Email: phải nhập dạng email, tận cùng là @fpt.edu.vn

Để kiểm tra dữ liệu như thế , chúng ta sẽ sử dụng chức năng validation trong Laravel

Kiểm tra dữ liệu với hàm validate

Để kiểm tra dữ liệu từ form gửi lên, Bạn có thể dùng hàm validate() của đối tượng $request. Các rules viết trong validate() để diễn tả các quy tắc mong muốn. Mỗi rule có key là name của form field, còn value là 1 string hoặc array.

Nếu validate() kiểm tra fail thì một exception được tạo ra và báo lỗi sẽ trả về cho user.,nếu pass thì code vẫn tiếp tục chạy.

public function sv_store(Request $request) {
  $request->validate([
      'ht' => ['required','min:3','max:20'],
      'tuoi' => 'required|integer|min:16|max:100',
      'ns' =>['required','date'],
      'cmnd' => 'digits_between:9,10',
      'email' => 'email|ends_with:@fpt.edu.vn'
      ]
   );
   //echo "Code xử lý";
}

Muốn dừng kiểm tra ngay khi gặp lỗi thì dùng bail trong rule:

$request->validate([
  'tuoi' => 'bail|required|integer|min:16|max:100',
]);

Hiện thông báo lỗi khi validate

Khi có lỗi, Laravel sẽ lưu các thông báo lỗi vào mảng $errors. sau đó redirect trở lại trang web gốc. Như trong ví dụ trên, Laravel sẽ redirect trở lại route sv khi validation fail. Vì vậy bạn có thể cho hiện lỗi trong view formnhapsv

@if ($errors->any())
<div class="alert alert-danger">
   <ul>
    @foreach ($errors->all() as $error)
      <li>{{ $error }}</li>
    @endforeach
    </ul>
</div>
@endif

Tùy chỉnh các chuỗi giá trị báo lỗi

Các chuỗi báo lỗi được Laravel định nghĩa trong file  lang/en/validation.php. Bạn mở lên chỉnh các giá trị nếu muốn. Muốn có file này thì chạy lệnh php artisan lang:publish rồi mở file lên để sửa nhé.

Hiện lỗi validate cho từng field

Trong blade view, dùng hàm @error() để check lỗi cho từng field và hiện lỗi với biến $message :

<label>Họ tên</label>
<input value="{{old('ht')}}" class="form-control" name="ht">
 @error('ht')
    {{ $message }}
 @enderror

Lưu ý: Thường hiện lỗi cho 1 field sẽ hiện ngay tại vị trí của field, và Bạn có thể dùng hàm old trong blade để hiện lại giá trị trong field mà user đã nhập.

Tạo request class trong Laravel

Request class dùng để điều chỉnh hoạt động kiểm tra báo lỗi của Laravel. Để tạo một request class, Bạn sử dụng lệnh sau :

php artisan make:request RuleNhapSV

Lệnh trên sẽ tạo class trong folder app/Http/Requests. Trong class có sẵn 2 hàm authorize() rules(). Hàm authorize() dùng để cho/cấm request class (return true/false) còn hàm rules() là nơi khai báo các quy tắc kiểm tra dữ liệu. Ngoài ra bạn có thể định nghĩa 2 hàm nữa là message() attributes()

Định nghĩa rules, authorize và messages trong request class

Trong hàm rules, khai báo các quy tắc kiểm tra:

public function rules() {
   return [
   'ht' => ['required','min:3','max:20'],
   'tuoi' => 'required|integer|min:16|max:100',
   'ns' =>['required','regex:/\d{1,2}\/\d{1,2}\/\d{4}/'],
   'cmnd' => 'digits_between:9,10',
   'em' => 'email|ends_with:@fpt.edu.vn'
   ];
}

Hàm authorize() trả về true/false sẽ cho/cấm request

public function authorize() {  return true; }

Định nghĩa các thông báo thân thiện tùy theo lỗi

Dưới hàm rules(), bạn tạo hàm messages() để định nghĩa các thông báo thân thiện tùy theo lỗi như sau:

public function messages() {
   return [
    'ht.required' => 'Phải nhập họ tên chứ',
    'ht.min' => 'Họ tên ngắn quá vậy',
    'ns.required' => 'Nhập ngày sinh nữa',
    'tuoi.required' => 'Nhập :attribute vào đi',
    'cmnd.digits_between' => 'CMND nhập 9 hoặc 10 ký tự'
  ];
}

Dùng request class trong controller

B1. Ở đầu controller dùng lệnh : 

use App\Http\Requests\RuleNhapSV;

B2: Trong action, chỉ định tham số có kiểu là request class đã tạo:

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\RuleNhapSV;
class SvController extends Controller {
   public function sv(){ return view("formnhapsv"); }
   public function sv_store(RuleNhapSV $request) {
      // "Code xử lý";
   }
}

Submit form, sẽ thấy kết quả

Tạo rule kiểm tra mới

Sử dụng lệnh make:rule của artisan để tạo rule mới trong Laravel

php artisan make:rule Chuhoa

File rule mới trong App\Rules\chuhoa.php. Trong đó có sẵn hàm validate() là nơi viết code định nghĩa dữ liệu như thế nào là sai.

<?php
namespace App\Rules;
use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
class Uppercase implements ValidationRule {
    public function validate(string $attribute, mixed $value, Closure $fail): void
    {
         if (strtoupper($value) !== $value) {
            $fail('Thuộc tính :attribute phải là chữ hoa bạn ơi!');
        }  
    }
}

Sử dụng rule mới tạo

Dùng lệnh use App\Rules\Chuhoa;

Tại vị trí khai báo các rule (trong controller hoặc mail rule), tạo instance cho rule bằng từ khóa new

Validation trong Laravel là hoạt động cần phải thực hiện mỗi khi bày ra các form. Mục đích là để có được dữ liệu có ý nghĩa từ người dùng. Tham khảo thêm ở link này nhé https://laravel.com/docs/10.x/validation