Validation trong Laravel 5.3 P2

Xin chào các bạn. Hôm nay mình sẽ tiếp tục giới thiệu về Validation trong Laravel 5.3 cho các bạn.

Ở bài trước mình đã giới thiệu tổng quát về Validation cũng như cách tạo một Validation cơ bản và Tạo Form Request Validation. Bài viết này mình sẽ đi sâu hơn vào Validation và sẽ giới thiệu những phần còn lại của Validation trong Laravel 5.3 cho các bạn.

4.Tự tạo Validator

Nếu bạn không muốn sử dụng phương thức ValidatesRequests là đặc tính của validate. Thì bạn có thể tự tạo ra một Validator Instans của mình bằng Validatorfacade. Phương thức make trong facade sinh ra một Validator Instance mới:

namespace App\Http\Controllers;

use Validator;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class PostController extends Controller
{
    /**
     * Store a new blog post.
     *
     * @param    Request  $request
     * @return  Response
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ]);

        if ($validator->fails()) {
            return redirect('post/create')
                        ->withErrors($validator)
                        ->withInput();
        }

        // Store the blog post...
    }
}

Đối số đầu tiên truyền vào phương thức make là dữ liệu cần được Validation/ Đối số thứ hai là một mảng quy định Validation được áp dụng vào dữ liệu.

Sau khi kiểm tra request validation không thành công, các bạn có thể dùng phương thức withErrors để flash nội dung lỗi vào session. Khi sử dụng phương thức này thì biến $errors sẽ tự động được gửi đến Views sau khi đã chuyển trang, cho phép bạn dễ dàng hiển thị chúng cho người dùng. Phương thức withErrors chấp nhận một Validator, MessageBag hoặc một Array PHP.

Redirection tự động

Nếu bạn muốn tạo mới một Validator Instance nhưng sẽ vẫn tự động chuyển trang bởi ValidatesRequest, bạn có thể gọi phương thức validate trong một Validator Instance hiện tại. Nếu validation thất bại thì người dùng sẽ tự động được chuyển trang hoặc trong trường hợp là một Ajax Request, sẽ có một Json Response được trả về :

Validator::make($request->all(), [
    'title' => 'required|unique:posts|max:255',
    'body' => 'required',
])->validate();

Named Error Bags

Nếu bạn có nhiều form trên một trang thì có thể sử dụng phương thức MessageBag sẽ cho phép nhận nội dung lỗi từ form cụ thể. Đơn giản chỉ là truyền thêm một tham số thứ hai của phương thức withErrors:

return redirect('register')
            ->withErrors($validator, 'login');

Bạn cũng có thể lấy một instansce MessageBag từ biến $errors:

{{ $errors->login->first('email') }}

Sau khi Validation Hook

Ngoài ra validator còn cho phép bạn thêm callbacks để chạy sau khi validation thành công. Điều này cho phép dễ dàng thực hiện các Validation và thêm nội dung cho Message Collection. Để bắt đầu, sử dụng phương thức after trong một Validator Instance:

$validator = Validator::make(...);

$validator->after(function($validator) {
    if ($this->somethingElseIsInvalid()) {
        $validator->errors()->add('field', 'Something is wrong with this field!');
    }
});

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

5.Làm việc với nội dung lỗi.

Sau khi gọi phương thức errors trong một Validator Instance. Bạn sẽ nhận được một instance Illuminate\Support\MessageBag sẽ có một phương thức làm việc với nội dung lỗi. Biến $erros sẽ tự động được tạo cho tất cả các View. Ngoài ra nó cũng là một instance của class MessageBag.

Nhận về nội dung lỗi đầu tiên của một trường.

Để nhận về lỗi đầu tiên của một trường, sử dụng phương thức first:

$errors = $validator->errors();

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

Nhận về tất cả nội dung lỗi của một trường.

Nếu bạn cần nhận một mảng nội dung của tất cả lỗi của một trường, sử dụng phương thức get:

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

Nếu bạn Validating một mảng các trường của form, bạn có thể nhận về tất cả nội dung cho mỗi phần tử của mảng bằng cách sử dụng ký tự "*":

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

Nhận về tất cả các lỗi của tất cả các trường.

Để nhận một mảng tất cả các nội dung của tất cả các trường, sử dụng phương thức all:

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

Xác định nội dung của một trường có tồn tại.

Phương thức has có thể sử dụng để xác định bất kỳ nội dung lỗi tồn tại của một trường:

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

Tùy biến nội dung.

Nếu cần. Các bạn có thể tùy biến nội dung lỗi cho Instance Validation mặc định. Có một vài cách để làm việc này. Đầu tiên các bạn có thể truyền tùy biến nội dung như là tham số thứ ba của hàm Validator::make:

$messages = [
    'required' => 'The :attribute field is required.',
];

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

Trong ví dụ trên thuộc tính :attribute Place-Holder sẽ thay thế bởi tên thực tế của trường Validation.Ngoài ra các bạn có thể sử dụng Place-Holders trong nội dung Validation. Ví dụ:

$messages = [
    'same'    => 'The :attribute and :other must match.',
    'size'    => 'The :attribute must be exactly :size.',
    'between' => 'The :attribute must be between :min - :max.',
    'in'      => 'The :attribute must be one of the following types: :values',
];

Tùy biến nội dung của thuộc tính cụ thể.

Thỉnh thoảng các bạn có thể tùy biến nội dung lỗi duy nhất một trường. Bạn có thể sử dụng dấu chấm. Chỉ định tên của thuộc tính đầu tiên:

$messages = [
    'email.required' => 'We need to know your e-mail address!',
];

Tùy biến nội dung trong file ngôn ngữ.

Trong hầu hết các trường hợp, các bạn có thể tùy biến nội dung trong một file ngôn ngữ thay vì truyền chúng trực tiếp vào phương thức Validator. Để làm điều này các bạn thêm nội dung vào mảng custom trong file ngôn ngữ resources/lang/xx/validation.php.

'custom' => [
    'email' => [
        'required' => 'We need to know your e-mail address!',
    ],
],

Tùy biến thuộc tính trong file ngôn ngữ.

Nếu bạn muốn thuộc tính :atribute phần nội dung Validation sẽ được thay đổi bởi tên thuộc tính tùy chỉnh, các bạn có thể tùy biến trong mảng attributes của file ngôn ngữ resources/lang/xx/validation.php:

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

6.Thêm quy định có điều kiện.

Validating khi xuất hiện.

Trong một số trường hợp, các bạn có thể muốn chạy Validation kiểm tra lại trường "only" nếu trường đó xuất hiện trong mảng input.Để có thể nhanh chóng làm điều này, thêm sometimes vào trong danh sách quy tắc rule:

$v = Validator::make($data, [
    'email' => 'sometimes|required|email',
]);

Trong ví dụ trên, trường email sẽ chỉ được validated nếu nó xuất hiện trong mảng $data.

Thêm quy định có điều kiện.

Đôi khi các bạn muốn thêm quy định trong logic.Ví dụ các bạn có thể muốn yêu cầu một trường có giá trị nếu trường khác có giá trị lớn hơn 100.Hoắc các bạn muốn 2 trường có giá trị chỉ khi trường khác xuất hiện. Để làm việc đó không có gì khó khăn cả.Đầu tiên tạo một Instance Validator với static rules sẽ không bao giờ thay đổi:

$v = Validator::make($data, [
    'email' => 'required|email',
    'games' => 'required|numeric',
]);

Giả sử bây giờ ứng dụng web của các bạn là sưu tầm game.Nếu một người sưu tầm game đăng kí ứng dụng của bạn và họ có nhỏ hơn 100 games, chúng ta muốn họ giải thích tại sao họ có quá nhiều game. Ví dụ có thể họ chạy một shop bán game hoặc có thể họ thích sưu tầm.Để có thể yêu cầu này, chúng ta có thể sử dụng phương thức sometimes trong Instance Validator.

$v->sometimes('reason', 'required|max:500', function($input) {
    return $input->games >= 100;
});

Tham số thứ nhất truyền vào phương thức sometimes là tên của trường chúng ta muốn Validate.Tham số thứ hai là quy định chúng ta muốn thêm.Nếu truyền Closure như là tham số thứ ba trả về true, quy định sẽ được thêm.Phương thức này làm cho việc thêm quy định Validate phức tạp trở lên dễ dàng hơn ngay cả khi các bạn muốn thêm nhiều Validate cho nhiều trường:

$v->sometimes(['reason', 'cost'], 'required', function($input) {
    return $input->games >= 100;
})

7.Validating mảng.

Validating mảng các trường của form không có gì khó khăn.Ví dụ để Validate mỗi email trong mảng trường input là unique, có thể làm như sau:

$validator = Validator::make($request->all(), [
    'person.*.email' => 'email|unique:users',
    'person.*.first_name' => 'required_with:person.*.last_name',
]);

Tương tự như vậy, Các bạn có thể sử dụng ký tự "*" khi muốn chỉ định nội dung Validation trong file ngôn ngữ giúp dễ dàng sử dụng một file nội dung Validate cho mảng:

'custom' => [
    'person.*.email' => [
        'unique' => 'Each person must have a unique e-mail address',
    ]
],

8.Tùy biến quy định validation.

Laravel cung cấp một số quy định validation rất hữu ích.tuy nhiên, có thể các bạn muốn tạo Validate bởi chính bạn. Một phương thức đăng ký tùy biến quy tắc Validationlà sử dụng phương thức extend trong Validator facade. Chúng ta sẽ sử dụng nó trong một service provider để đăng ký tùy biến quy tắc validation:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Validator;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return  void
     */
    public function boot()
    {
        Validator::extend('foo', function($attribute, $value, $parameters, $validator) {
            return $value == 'foo';
        });
    }

    /**
     * Register the service provider.
     *
     * @return  void
     */
    public function register()
    {
        //
    }
}

Tùy biến validator Closure nhận bốn đối số: tên của $attributeđược validate, giá trị $value của thuộc tính, một mảng quy định $parameters, và một Instance Validator.

Các bạn cũng có thể truyền một class và method vào phương thức extend thay vì một Closure:

Validator::extend('foo', '[email protected]');

Định nghĩa nội dung lỗi.

Các bạn có thể định nghĩa một nội dung lỗi cho quy định tùy biến của bạn. Bạn có thể làm như vậy hoặc một mảng nội dung tùy biến nội dung inline hoặc thêm vào validation file ngôn ngữ. Nội dung này sẽ được đặt ở trên đầu của mảng, không ở bên trong mảng custom,nó chỉ dành cho những nội dung lỗi attribute-specific:

"foo" => "Your input was invalid!",

"accepted" => "The :attribute must be accepted.",

// The rest of the validation error messages...

Khi các bạn tùy biến quy định Validation, đôi khi bạn cần định nghĩa tùy chỉnh place-holder thay thế nội dung lỗi. CÁc bạn cũng có thể tạo một Validator như miểu tả ở trên sau đó gọi phương thức replacertrong Validator facade. Các bạn có thể sử dụng trong phương thức boot của Service Provider:

/**
 * Bootstrap any application services.
 *
 * @return  void
 */
public function boot()
{
    Validator::extend(...);

    Validator::replacer('foo', function($message, $attribute, $rule, $parameters) {
        return str_replace(...);
    });
}

Implicit Extensions.

Mặc định, khi một thuộc tính đã được Validated sẽ không xuất hiện hoặc chứa một giá trị rỗng như định nghĩa bởi quy tắc required, quy tắc Validation thường bao gồm cả phần Extensions sẽ không hoạt động. Ví dụ, quy định unique sẽ không hoạt động nếu giá trị Null:

$rules = ['name' => 'unique'];

$input = ['name' => null];

Validator::make($input, $rules)->passes(); // true

Đối với quy tắc Validate hoạt động ngay cả khi thuộc tính là rỗng, quy định phải ngụ ý rằng các thuộc tính là bắt buộc. Như tạo một "implicit" Extension, sử dụng phương thức Validator::extendImplicit():

Validator::extendImplicit('foo', function($attribute, $value, $parameters, $validator) {
    return $value == 'foo';
});

Như vậy mình đã giới thiệu chi tiết về Validation trong Laravel 5.3.Hi vọng với những hướng dẫn của mình sẽ giúp được các bạn có thể tìm hiểu về Laravel tốt hơn.

Thao Khảo

https://laravel.com/docs/5.3