9. Làm việc với thông báo lỗi (Working with error message)

https://viblo.asia/p/tap-20-validation-laravel-GrLZDWAEKk0

Sau khi gọi method errors từ lớp khởi tạo Validator, bạn sẽ nhận một lớp khởi tạo Iluminate\Support\MessageBag, lớp này cung cấp nhiều method để làm việc với thông báo lỗi một cách thuận tiện. Biến $errors được tạo tự động đến tất cả các view cũng là một lớp khởi tạo MessageBag.

1. Lấy thông báo lỗi đầu tiên của một trường (Retrieving the first error message for a field)

Chúng ta sẽ sử dụng method first với tham số là tên input.

$errors = $validator->errors();

echo $errors->first('name_input');

2. Lấy tất cả thông báo lỗi của một trường (Retrieving all error messages for a field)

Để lấy tất cả thông báo lỗi của một trường bạn có thể sử dụng method get.

foreach ($errors->get('name_input') as $message) {
    //
}

Nếu như bạn validate một mảng input, bạn có thể nhận tất cả thông báo lỗi của mỗi phần tử trong mảng bằng cách sử dụng ký hiệu *.

foreach ($errors->get('files.*') as $message) {
    //
}

3. Lấy tất cả thông báo lỗi của tất cả trường (Retrieving all error messages for all fields)

Để làm được điều này, ta chỉ cần gọi method all.

foreach ($errors->all() as $message) {
    //
}

4. Kiểm tra thông báo lỗi có tồn tại của một trường (Checking if an message error exists for a field)

Bạn có thể sử dụng method has với tham số là tên input cần kiểm tra.

if ($errors->has('name_input') {
    //
}

Lứu ý: Các method tren có thể áp dụng tại $errors trong blade template.

5. Tùy chỉnh thông báo lỗi (Customizing error message)

Nếu cần thiết, bạn có thể thay đổi các thông báo lỗi mặc định. Có nhiều cách để làm điều này. Đầu tiên bạn có thể truyền các thông báo lỗi tại tham số thứ ba của method Validator::make.

$messages = [
    'required' => ':attribute không được bỏ trống.'
];

$validator = Validator::make($input, $rules, $messages);

Trong ví dụ trên, từ khóa :attribute sẽ được thay thế bằng tên thực của input trong validation. Ngoài ra còn có một số từ khóa khác tương ứng với mỗi rule, bạn có thể mở file resources/lang/en/validation.php để tham khảo. Chẳng hạn:

// ...
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
// ...

Lưu ý: Với các từ khóa thay thế, nếu tên input có dạng name_input thì sau khi tạo thông báo tùy chỉnh sẽ đổi thành name input.

a. Chỉ định một thông báo tùy chỉnh cho một thuộc tính nhất định (Specifying a custom message for a given field)

Việc này tương tự với việc định nghĩa method messages trong form request, bạn có thể sử dụng cú pháp key name_field.name_rule để thay đổi thông báo mặc định.

$messages = [
    'title.required' => 'Tiêu đề bài viết không được bỏ trống.'
];

b. Chỉ định thông báo tùy chỉnh trong tệp ngôn ngữ (Specifying custom message in language file)

Nếu ứng dụng của bạn có nhiều validator có cùng chung một thông báo tùy chỉnh, nhưng việc khai báo ở từng chỗ như vây sẽ rất tốn thời gian và cực kỳ khó khăn trong việc thay đổi. Bạn có thể khai báo các thông báo tùy chỉnh của mình trong file resources/lang/xx/validation.php tại mảng custom.

'custom' => [
    'attribute-name' => [
        'rule-name' => 'custom-message',
    ],
],

xx ở đây chính là thư mục chứa các file ngôn ngữ của ứng dụng, mặc định Laravel khởi tạo thư mục en. Nếu muốn thay đổi mặc định này, bạn có thể tạo thư mục resources/lang/vi chẳng hạn, sau đó copy toàn bộ các file ngôn ngữ có trong thư mục en qua thư mục vừa khởi tạo. Việc của bạn giờ rất đơn giản, chỉ việc chỉnh sửa các thông báo lỗi tiếng Anh thành tiếng Việt, chú ý giữ nguyên các từ khóa thay thế như :attribute, :other... Cuối cùng, ta chỉ việc thay đổi config tại config/app.php:

'locale' => 'vi',

Quay trở lại bài, để áp dụng cho ví dụ trên, ta có thể làm như sau:

'custom' => [
    'title' => [
        'required' => 'Tiêu đề bài viết không được bỏ trống.'
    ],
],

Như vậy ta không cần phải khai báo lại ở trình validator nữa.

c. Chỉ định thuộc tính tùy chỉnh trong tệp ngôn ngữ (Specifying custom attribute in language file)

Cũng giống như method attributes trong form request, ta cũng có thể thay thế các tên input thô thành các label linh động, dễ hiểu trong thông báo tùy chỉnh.

'attributes' => [
    'email' => 'email address',
],

d. Chỉ định giá trị tùy chỉnh trong tệp ngôn ngữ (Specifying custom value in language file)

Thỉnh thoảng bạn sẽ cần thay đổi giá trị của :value thay thế các giá trị thô. Chẳng hạn ứng dụng của chúng ta có trang thanh toán. Yêu cầu là nếu người dùng chọn hình thức thanh toán là thẻ tín dụng thì bắt buộc phải nhập số thẻ tín dụng, còn nếu chọn hình thức thanh toán khi nhận hàng thì không cần.

Đầu tiên mình sẽ khai báo hai route:

Route::get('payment', 'PaymentController@show');

Route::post('payment', 'PaymentController@pay');

Tiếp theo là khởi tạo blade view payment với nội dung như sau:

<h1>Payment</h1>

<form action="/payment" method="POST">
    @csrf 

    {{-- Hiển thị thông báo lỗi --}}
    @if ($errors->any()) 
        <ul>
            @foreach ($errors->all() as $message) 
                <li>{{ $message }}</li>
            @endforeach
        </ul>
    @endif

    <div>
        <p>Payment type</p>
        <select name="payment_type">
            <option value="cc">Credit card</option>
            <option value="od">On delivery</option>
        </select>
    </div>

    <div>
        <p>Credit card number (optional)</p>
        <input type="text" name="credit_card_number">    
    </div>    

    <br>

    <div>
        <button type="submit">Done</button>
    </div>
</form>

Đây là giao diện trang thanh toán của chúng ta:

Cuối cùng ta sẽ khởi tạo controller PaymentController với lệnh Artisan. Sau đó khai báo hai method showpay như sau:

public function show()
{
    return view('payment');
}

public function pay(Request $request)
{
    $request->validate([
        'credit_card_number' => 'required_if:payment_type,cc'
    ]);
    
    return 'Payment success!';
}

Hãy chú ý tại rule required_if, nó có tác dụng sẽ bật kiểm duyệt require của một input nào đó khi input kia có giá trị nhất định. Như trường hợp trên, input credit_card_number sẽ bật kiểm duyệt require nếu input payment_type có giá trị là cc.

Ok, giờ ta test xem nhé, mình sẽ để payment_typecc và không nhập dữ liệu cho credit_number_card.

Nó xuất ra một câu thống báo lỗi theo cú pháp của required_if được khai báo trong file ngôn ngữ resources/lang/en/validation.php:

'required_if' => 'The :attribute field is required when :other is :value.',

Chú ý đến từ khóa thay thế :value ở cuối, nó đã được replace bằng cc, ứng với giá trị của input payment_type. Nhưng nếu thông báo như vậy, người dùng sẽ không hiểu hết nội dung, chính vì vậy ta có thể thay thế một lần nữa :value này bằng cách khai báo thêm mảng value trong file validation language.

'values' => [
    'payment_type' => [
        'cc' => 'credit card'
    ],
],

Bây giờ hãy nhìn lại kết quả:

Lưu ý: Mảng này chỉ áp dụng cho các từ khóa thay thế :value.

Còn tiếp...

Cảm ơn các bạn đã quan tâm theo dõi. Cùng đồng hành với mình qua những tập tiếp theo tại series "Hành trình chinh phục Laravel Framework" nhé! Chúc may mắn và hẹn gặp lại.

Last updated