Validation trong Laravel

Validation là hoạt động nhằm kiểm tra sự chính xác của dữ liệu đầu vào. Bạn sẽ đưa ra các quy tắc để kiểm tra xem dữ liệu có đúng với các quy tắc đó 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ố …

A. Chuẩn bị

  • Tạo route
use App\Http\Controllers\SvController;
Route::get("/sv",[SvController::class,'sv']);
Route::post("/sv",[SvController::class,'sv_store'])->name('sv_store');
  • Tạo Controllers/SvController.php 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){

   }
}
  • Tạo views/formnhapsv.blade.php
<link rel="stylesheet"  href= "https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/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>

Xem thử: http://localhost:8000/sv sẽ thấy kết quả

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

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

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

B. Viết code validation trong laravel

Để kiểm tra dữ liệu, bạn dùng hàm validate trong đối tượng $request. Nếu kiểm tra là ok (pass), code sẽ thực thi bình thường, ngược lại nếu fail thì một exception sẽ được tạo ra và thông báo lỗi sẽ trả về cho user.

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

Các quy tắc kiểm tra được khai báo trong hàm validate, mỗi quy tắc có key là name của form field còn value là 1 string hoặc aray liệt kê các quy tắc.

Nếu kiểm tra fail thì response tự động để trả về user. Nếu pass thì code vẫn tiếp tục thực thi.

Dừng ngay khi kiểm tra fail

Nếu bạn muốn dừng kiểm tra ngay khi lần đầu gặp lỗi thì dùng bail trong rule:

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

Trong ví dụ trên, nếu required trên tuoilà fail thì rule integer sẽ không được check . Các rule được kiểm tra theo thứ tự được khai báo.

C. Hiện thông báo lỗi

Khi kiểm tra không pass , Laravel sẽ tự động redirect trở lại trang web cho user. Các thông báo lỗi được tự động ghi nhận vào session. Biến $errors là 1 instance của lớp Illuminate\Support\MessageBag chứa tẩt cả các thông báo lỗi

Trong ví dụ trên, user will được redirect trở lại create sv trong SvController khi validation fails, vì vậy bạn có thể hiện lỗi trong view (trước tag form):

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

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

Trong balde view, bạn có thể dùng hàm @error để check lỗi cho 1 field và hiện với biến $message theo ví dụ sau:

value="{{ old('hoten') }}"  type="text" class="form-control" name="hoten">
@error('hoten')
    {{ $message }} 
@enderror
Lưu ý: 
- Thường hiện giá trị lỗi cho 1 field sẽ hiện ngay tại vị trí của field
- Hàm old trong blade giúp bạn hiện lại giá trị cũ trong field mà user đã nhập. Xem ví dụ trên

Error validation trong các request ajax

Đối với các request dạng ajax thì Laravel không redirect response như khi kiểm tra dữ liệu từ form gửi lên. Thay vào đó là Laravel sẽ phát sinh 1 response JSON chứa tất cả các thông báo lỗi . Response JSON này được sang với mã http là 422

D. Tạo request class để validate tốt hơn

Tạo request sẽ giúp bạn dễ dàng điều chỉnh hoạt động kiểm tra và thông báo lỗi.

Để tạo request class, bạn sử dụng lệnh make:request của artisan :

php artisan make:request RuleNhapSV

Lệnh trên sẽ tạo class trong folder app/Http/Requests . Bạn mở file lên sẽ thấy có sẵn 2 hàm authorize(), rules(). Và bạn có thể định nghĩa thêm 2 hàm nữa là messages() , attributes()

  • Hàm rules(): nơi khai báo các quy tắc kiểm tra dữ liệu. Hàm trả về 1 array các quy tắc.
  • Hàm authorize(): dùng để cho phép/cấm dùng class này. Hàm này trả về true (cho phép), false(cấm)
  • Hàm message(): Trong class request bạn có thể khai báo hàm này để định nghĩa các chuỗi thông báo lỗi theo ý mình (tiếng việt)
  • Hảm attributes(): Trong class request bạn có thể khai báo hàm này để định nghĩa tên thân thiện cho các field. Ví dụ field hoten có tên thân thiện là Họ tên

Khai báo các rules trong class request

Trong file request đã tạo, đã có sẵn hàm rule . Đó là nơi bạn khai báo các rule muốn kiểm tra dữ liệu nhập của user

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'
        ];
}

Authorize request class

Trong request class, hàm authorize() trả về true sẽ cho phép class request hoạt động, ở đây bạn có thể thực hiện các tính toán nghiệp vụ cần thiết trước khi quyết định trả về true hay false

public function authorize() {
   return true;
}

Định nghĩa các chuỗi báo lỗi thân thiện

Trong request class, bạn có thể định nghĩa các chuỗi thông báo lỗi tùy ý (bằng tiếng việt) để khi hiện ra sẽ thân thiện hơn với người dùng.

public function messages() {
    return [
        'ht.required' => 'Phải nhập họ tên chứ',
        'ht.min' => 'Họ tên ngắn quá vậy',
        'ht.max' => 'Trời ơi họ tên quá dài bồ ơi',
        'ht.chuhoa' => 'Họ tên chữ hoa nhe',
        'ns.required' => 'Nhập ngày sinh nữa',
        'tuoi.required' => 'Nhập :attribute vào đi',
        'tuoi.integer' => ':attribute phải là số chứ ta',
        'tuoi.min' => ':attribute nhỏ quá, phải>=16',
        'tuoi.max' => ':attribute quá lớn rồi, <=100 nhé',
        'cmnd.digits_between' => ':attribute nhập 9 hoặc 10 ký tự'
    ];
}

Khai báo tên thân thiện các field kiểm tra

Các field trong form được kiểm tra dữ liệu thường có name không dấu. Ví dụ hoten, tuoi… nên khi dùng trong các chuỗi báo lỗi sẽ không được thân thiện. Bạn có thể định nghĩa lại trong hàm attributes() của request class

public function attributes(){
return [
    'ns' => 'Ngày sinh',
    'ht' => 'Họ tên',
    'tuoi' => 'Tuổi',
    'cmnd' => 'Số chứng minh nhân dân'
];
}

Sử dụng request class trong controller

Request class giúp bạn định nghĩa các rule, các thông báo lỗi thân thiện…Vậy dùng request class thế nào? 2 bước:

B1. Trong controller, trước tên controller , khai báo lệnh use để nhúng request class vào controller:

use App\Http\Requests\RuleNhapSV;

B2: Trong action xử lý của controller, khai báo đối tượng $request có kiểu là request class đã tạo:

function sv_store(RuleNhapSV $request){
    //echo "Code xử lý tiếp tục";
}

E. Danh sách các rule kiểm tra dữ liệu trong Laravel

F. Tạo rule kiểm tra mới trong Laravel

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

php artisan make:rule Chuhoa

File rule mới bạn tạo được đặt trong folder App\Rules. Mở file mới tạo, bạn sẽ thấy có sẵn 2 hàm : passes()- trả về true/false và message() – trả về chuỗi .

Hàm passes() là nơi bạn viết code để định nghĩa dữ liệu như thế nào là pass. Hàm message() là thông báo khi dữ liệu không pass

Rule;
class Chuhoa implements Rule {
    public function __construct() {
        //
    }
    public function passes($attribute, $value) {
        return strtoupper($value) === $value;
    }
    public function message() {
        return 'Thuộc tính :attribute phải là chữ hoa bạn ơi!';
    }
}

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

Dùng lệnh use để nhúng rule mới tạo:

use App\Rules\Chuhoa;

Tại vị trí khai báo các rule, tạo instance cho rule bằng từ khóa new

public function rules() {
    return [
        'ht' => ['required','min:3','max:20', new Chuhoa],
        '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'
    ];
}