Validation trong Laravel phần 1

1. Simple request validate

Để hiểu được cách xử dụng của ValidatesRequests trait trong Laravel ta sẽ sử dụng ví dụ với form nhập liệu như sau:

Với các yêu cầu về dữ liệu nhập vào được xét như sau:

  • Tất cả các field không được để trống
  • username chỉ gồm các chữ cái và n kí tự thỏa mãn: 4 <= n <= 10
  • email đúng định dạng email
  • password gồm tối thiểu 8 kí tự
  • passwrod confirm phải giống với password

Nếu bạn tham khảo document cho phần validation trong Laravel ta được cung cấp một ví dụ như sau:

public function store(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);
}

Theo như document là Laravel cung cấp, ở đây, ta đang sử dụng chức năng validate() được cung cấp bở class Request, nếu các field của chúng ta thỏa mãn các điều kiện theo yêu cầu thì hàm store sẽ tiếp tục xử lý bình thường. Nếu mộ trong các field không thỏa mã yêu cầu sẽ sinh ra Exception đồng thời trả lại lỗi cho người dùng ở dạng phù hợp (có thể dạng HTTP Response hoặc JSON nếu request trước đó là ajax). Nội dung đoạn code trên được hiểu đơn giản như sau:

  • Object Request sẽ thực hiện kiểm tra các field từ form mà người dùng nhập với tên field là key của mảng, VD: với key là title như hình ta thấy ở trên thì thực chất bên HTML sẽ là thẻ input có name tương ứng là titlenhư sau:<input type="text" name="title">
  • Tương tự với các key còn lại trong mảng mà ta truyền vào hàm validate() cũng là name của các field mà ta muốn tiến hành kiểm trả dữ liệu
  • Tiếp đến phần value ứng với mỗi key đó chính là những nội dung mà chúng ta cần kiểm tra với field. Cụ thể với field title, ta có điều kiện:'title' => 'required|unique:posts|max:255',
  • Điều này có nghĩa là với field title ta sẽ kiểm tra 3 điều kiện với mỗi điều kiện sẽ cách nhau bởi dấu |, các điều kiện lần lượt là:
    • required – title phải tồn tại trong request gửi lên đồng thời không được để trống
    • unique:posts – title nội dung của nó phải là duy nhất đối với bảng posts
    • max:255 – Độ dài tối đa của title tính theo số kí tự là 255 kí tự
  • Đây là các điều kiện có sẵn mà chức năng Validation trong Laravel cung cấp sẵn cho chúng ta, để có thể tìm hiểu kĩ hơn về các điền kiện kiểm tra này, bạn có thể tham khảo tại đây.

Để thử nghiệm chức năng trên đối với form của chúng ta, ta sẽ sửa lại đôi chút hàm ban đầu như sau:

public function store(Request $request)
{
    $validatedData = $request->validate([
        'username' => 'required',
        'email' => 'required',
        'password' => 'required',
        'password_confirmation' => 'required',
    ]);
}

Với usernameemailpasswordpassword_confirmation là name của các input field mà ta đặt bên html. Với đoạn code xử lý kiểm tra dữ liệu như trên, khi ta submit form mà không nhập bất cứ nội dung gì cả, thì đây sẽ là những gì ta thu được:

Lưu ý : ta nhận được khung đỏ báo lỗi không phải do Laravel tự sinh cho chúng ta mà do chúng ta tạo. Cụ thể sẽ nói rõ trong phần sau. Như bạn có thể thấy, khi chúng ta không nhập dữ liệu gì, đoạn code kiểm tra dữ liệu của chúng ta sẽ thực hiện kiểm trả cả 4 field được nêu ra trong mảng cùng với điều kiện của 4 field đó là required. Do tất cả các field ta đều để rỗng dẫn đến việc kiểm tra dữ liệu trả về là không chính xác và tự động quay lại (redirect) về form của chúng ta với nội dung báo lỗi như ở khung đỏ trong hình ở trên. Đoạn code trên ta đã đảm bảo được điều kiện thứ nhất trong danh sách các yêu cầu mà chúng ta cần thực hiện là tất cả các field không được để trống. Tiếp theo ta sẽ lần lượt thêm các điều kiện cho mỗi field để hoàn thiện các điều kiện đã đặt ra như sau:

public function store(Request $request)
{
    $validatedData = $request->validate([
        'username' => 'required|alpha|min:6|max:10',
        'email' => 'required|email',
        'password' => 'required|min:8',
        'password_confirmation' => 'required|same:password',
    ]);
}

Sau khi thử nhập lại dữ liệu nhưng vẫn vi phạm điều kiện như sau:

Đây là kết quả mà chúng ta thu được:

Như bạn thấy, do các field của chúng ta đã vi phạm các điều kiện mới mà chúng ta đặt ra nên sẽ trả lại lỗi đúng như các điều kiện mà nó đã vi phạm. Tuy nhiên trong trường hợp bạn muốn với mỗi field ta sẽ dừng lại không kiểm tra điều kiện tiếp theo nếu điều kiện trước đó lỗi thì ta cần thêm điều kiện bail ở đầu danh sách điều kiện của mỗi field như sau:

public function store(Request $request)
{
    $validatedData = $request->validate([
        'username' => 'bail|required|alpha|min:6|max:10',
        'email' => 'bail|required|email',
        'password' => 'bail|required|min:8',
        'password_confirmation' => 'bail|required|same:password',
    ]);
}

Khi đã thêm điều kiện bail cho mỗi field thì cùng với form nhập liệu lỗi ngay phía trên thì kết quả mà ta thu được cũng sẽ như sau:

Như bạn thấy username giờ chỉ báo lỗi do ta nhập cả số và kí tự chứ không còn báo lỗi về số kí tự tối thiểu như trước nữa do khi vi phạm điều kiện alpha thì field này được dừng lại không tiếp tục kiểm tra các lỗi khác nữa. Để thực sử dụng các điều kiện một cách chính xác và hợp lý thì trước khi dùng bạn nên tham khảo lại document để xem cách dùng cũng như những gì đã được hỗ trợ sẵn.

2. Custom validation

Trong trường hợp bạn không muốn dùng hàm validate() được cung cấp bởi class Request và muốn tự mình quyết định khi có lỗi sẽ thực hiện hành động gì hoặc chuyển hướng đi đâu thì thứ bạn cần chính là sử dụng Validator facades. Về cú pháp và cách dùng cùng tương tự như cách làm trên:

public function store(Request $request)
{
    $validator = Validator::make($request->all(), [
        'username' => 'bail|required|alpha|min:6|max:10',
        'email' => 'bail|required|email',
        'password' => 'bail|required|min:8',
        'password_confirmation' => 'bail|required|same:password',
    ]);

    if ($validator->fails()) {
        // Do something
    }
}

Lưu ý: bạn sẽ cần phải thêm use Validator; ở đầu controller để thực hiện chức năng này Ở đây, thay vì ta kiểm tra dữ liệu từ request thì ta sẽ sử dụng Validator facades và gọi đến chức năng make() với tham số truyền vào đầu tiên là tất cả các field trong request thông qua $request->all() và tham số thứ 2 là mảng chứa các điều kiện cần kiểm tra. Validator::make() sẽ chịu trách nghiệm kiểm tra các field sau đó tạo trả về một instance của class Validator và ta sẽ lưu vào biến validator. Từ biến này ta có thể gọi đến hàm fails() để kiểm tra xem có điều kiện kiểm tra nào không hợp lệ hay không rồi từ đó có thể đưa ra cách xử lý như mong muốn.

3. Form Request Validation

Bằng cách sử dụng 2 phương pháp trên chắc chắn sẽ tiết kiệm cho bạn rất nhiều công sức trong việc kiểm tra dữ liệu người dùng cũng như làm gọn lại function của mình. Tuy nhiên vẫn có những lúc bạn cảm thấy rằng việc thêm dù chỉ là vài dòng code liên quan đến việc kiểm tra dữ liệu người dùng trong function của controller là vẫn dài và hơn nữa controller cũng không cần phải biết đến việc này thì bạn có thể tách việc kiểm tra dữ liệu bằng cách tạo một class riêng cho nó cùng với một hàm kiểm tra cho form tương ứng và gọi nó trong controller của mình, việc đó có thể làm như sau:

<?php

namespace App\Validations;

class Validation
{
    public static function validateSignupRequest($request)
    {
        return $request->validate([
            'username' => 'bail|required|alpha|min:6|max:10',
            'email' => 'bail|required|email',
            'password' => 'bail|required|min:8',
            'password_confirmation' => 'bail|required|same:password',
        ]);
    }
}

Ta cũng có thể làm tương tự với Validator::make() Sau đó ta chỉ việc thêm class mới này vào controller bằng cách use App\Validations\Validation; và sau đó sử dụng như sau:

public function store(Request $request)
{
   Validation::validateSignupRequest($request);
}

Cách làm trên sẽ cho ta kết qua tương tự như ta mong đợi. Tuy nhiên, thay vì phải tự tạo class mới như vậy thì Laravel cung cấp sẵn cho chúng ta một phương pháp tương tự nhưng đơn giản và thậm chí ngắn gọn hơn nhiêu khi sử dụng trong controller đó là sử dụng FromRequest. Để tạo một class riêng cho một form dữ liệu ta dùng lệnh sau trên terminal (command line):

$ php artisan make:request <className>

Ở đây ta sẽ sử dụng class là SignupRequest và sau khi thực hiện lệnh trên Laravel sẽ tạo cho chúng ta một folder mới tên là file mới nằm trong folder app\Http'Controllers\Requests có tên là SignupRequest.php và có nội dung như sau:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class SignupRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            //
        ];
    }
}

Class này gồm có 2 hàm chính: – authorize(): dùng để xác định xem người dùng nào có quyền thực hiện request này. Tạm thời chúng ta sẽ không quan tâm đến nó và để nó true tương ứng với ai cũng có thể thực hiện request này – rules(): đây là nơi định nghĩa quy định cho các field của chúng ta, ta sẽ sửa lại bằng cách copy phần validate ở trên vào đây:

public function rules()
{
    return [
        'username' => 'bail|required|alpha|min:6|max:10',
        'email' => 'bail|required|email',
        'password' => 'bail|required|min:8',
        'password_confirmation' => 'bail|required|same:password',
    ];
}

Cuối cùng ở hàm store() bên controller ta thay thế Request mặc định truyền vào bằng SignupRequest như sau:

public function store(SignupRequest $request)
{
  // Do something
}

Lúc này hàm store() của bạn sẽ được thực hiện khi toàn bộ các điều kiện đối với các filed trong class SignupRequest được thỏa mãn. Vì thể ở hàm này bạn chỉ cần lo code chức năng lưu trữ của nó chứ không còn cần viết phần kiểm tra dữ liệu nữa. Tất nhiền bạn cần thêm use App\Http\Controllers\Request\SignupRequest ở dầu controller để sử dụng được class này. Với cách làm này, code bạn đã trở nên tối ưu và ngắn gọn hơn rất nhiều so với phần code khi chúng ta bắn đầu.

Leave a reply:

Your email address will not be published.

Site Footer

Sliding Sidebar

Facebook