Laravel cơ bản
Laravel nâng cao
Quảng cáo

Validation trong Laravel

Trong hướng dẫn này chúng ta cùng đi nghiên cứu cách xác thực và kiểm tra dữ liệu (Validation) trong Laravel 8.

Làm sao để kiểm tra, xác thực thông tin người dùng gửi lên trong các dự án PHP là một vấn đề quan trọng liên quan đến bảo mật. Trong hướng dẫn này chúng ta cùng đi xem xét vềvalidation trong Laravel8, một phần không thể thiếu trong các ứng dụng.

Giới thiệu về validation trong Laravel.

Laravel cung cấp cho cũng ta nhiều cách để xác thực, kiểm tra dữ liệu. Trong đó cách phổ biến nhất là xác thực các dữ liệu người dùng gửi lên HTTP request.

Trong laravel, validation được support rất mạnh và sử dụng cũng như mở rộng cũng rất dễ dàng.

Bạn có thể sử dụng rất nhiều cách để có thể validate được dữ liệu trong Laravel và ở phạm vi bài viết này mình sẽ giới thiệu với mọi người một số cách phổ biến nhất.

Validation sử dụng phương thức validate.

Để validate dữ liệu request gửi lên các bạn có thể sử dụng phương thức validate với cú pháp:

Ví dụ

$request->validate($rules, $customMessage);

Trong đó:

  • $rules là một mảng dữ liệu với key là các input name, value là các rule mà bạn muốn ràng buộc.
  • $customMessage là một mảng dữ liệu chứa các custom message của bạn. Trường này có thể bỏ trống.

VD: Validate input id bắt buộc phải có và phải là kiểu số.

Ví dụ

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::get('store', function (Request $request) {
    $request->validate([
        'id' => 'required|integer'
    ]);
})->name('store');

Ngoài cách ngăn cách giữa các rule bằng ký tự '|' bạn cũng có thể viết dưới dạng sau:

Ví dụ

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::get('store', function (Request $request) {
    $request->validate([
        'id' => ['required', 'integer']
    ]);
})->name('store');

Trong trường hợp validate mà không pass laravel sẽ trả về một response redirect về request trước đó, kèm theo các error message được flash xuống session.

Nếu trong trường hợp bạn cần Laravel response về luôn json error code, bạn cần phải truyền thêm tham số accept header application/json hoặc request của bạn là một XHR request.

Validation sử dụng form request.

Laravel cung cấp cho chúng ta thêm một cách để tạo ra các validate nằm ở trong file riêng biệt, chứa các logic phục vụ cho việc validate data và có thể tái sử dụng trong những trường hợp tương tự.

Để tạo ra form request trong Laravel, các bạn sử dụng câu lệnh artisan:

Ví dụ

php artisan make:request FormRequestName

Trong đó, FormRequestName là form request bạn muốn tạo.

VD: Mình sẽ tạo ra StoreContactRequest.

Ví dụ

php artisan make:request StoreContactRequest

Lúc này Laravel sẽ sinh ra cho các bạn một file nằm trong app/Http/Requests/StoreContactRequest.php. File này sẽ có nội dung như dạng như sau (tùy version):

Ví dụ

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

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

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

Trong đó:

Phương thức authorize sẽ quyết định xem người dùng có được thực thi request này hay không. Nếu trả về true thì người dùng được phép và ngược lại. Phương thức rules sẽ chứa các rule các bạn muốn validate.

VD: Mình sẽ chuyển validate ở ví dụ trên vào form request.

- app/Http/Requests/StoreContactRequest.php

Ví dụ

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreContactRequest 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 [
            'id' => ['required', 'integer']
        ];
    }
}

- routes/web.php

Ví dụ

use App\Http\Requests\StoreContactRequest;
use Illuminate\Support\Facades\Route;

Route::get('store', function (StoreContactRequest $request) {
    return 'pass';
})->name('store');

Đối với form request bạn cũng có thể custom được error mesage bằng cách trả về message trong phương thức message.

VD: Custom message required cho trường id.

Ví dụ

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreContactRequest 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 [
            'id' => ['required', 'integer']
        ];
    }

    public function messages()
    {
        return ['id.required' => 'Trường ID là bắt buộc'];
    }
}

Bạn cũng có thể sửa attribute name trong form request bằng cách sử dụng phương thức attributes.

VD: Sửa attribute "id" thành "contact id"

Ví dụ

/**
 * Get custom attributes for validator errors.
 *
 * @return array
 */
public function attributes()
{
    return [
        'id' => 'Contact id',
    ];
}

Trong một số trường hợp bạn muốn thực hiện thêm một số logic sau khi validate thực thi bạn có sử dụng phương thức after.

Ví dụ

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreContactRequest 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 [
            'id' => ['required', 'integer']
        ];
    }

    public function messages()
    {
        return ['id.required' => 'Trường ID là bắt buộc'];
    }

    /**
     * Configure the validator instance.
     *
     * @param  \Illuminate\Validation\Validator  $validator
     * @return void
     */
    public function withValidator($validator)
    {
        $validator->after(function ($validator) {
            // logic
        });
    }
}

Tương tự bạn cũng có thể chỉnh sửa input data trước khi thực hiện validate bằng cách sử dụng phương thức prepareForValidation.

VD: Xử lí slug input về dạng đường dẫn trước khi validate.

Ví dụ

use Illuminate\Support\Str;

/**
 * Prepare the data for validation.
 *
 * @return void
 */
protected function prepareForValidation()
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}

Validation sử dụng Validator.

Ngoài 2 cách trên, bạn cũng có thể sử dụng class Validator để validate với cú pháp:

Ví dụ

Validator::make($inputs, $rules, $messages $attributes);

Trong đó:

  • $inputs là một mảng dữ liệu chứa các dữ liệu bạn cần validate.
  • $rules là một mảng dữ liệu với key là các input name, value là các rule mà bạn muốn ràng buộc.
  • $messages là một mảng dữ liệu chứa các custom message của bạn. Trường này có thể bỏ trống.
  • $attributes là một mảng dữ liệu chứa các custom attribute của bạn. Trường này có thể bỏ trống.

Ví dụ

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;

Route::get('store', function (Request $request) {
    $validator = Validator::make($request->all(), [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);
})->name('store');

Lúc này để thực hiện validate các bạn sử dụng phương thức validate.

Ví dụ

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;

Route::get('store', function (Request $request) {
    Validator::make($request->all(), [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ])->validate();
})->name('store');

Hoặc bạn cũng có thể vừa validate và kiểm tra xem validate có lỗi hay không bằng cách sử dụng phương thức fails.

Ví dụ

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Validator;

Route::get('store', function (Request $request) {
    $validator = Validator::make($request->all(), [
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);
    if ($validator->fails()) {
        // validate fails
    }
})->name('store');

Hiển thị error massage.

Khi thực hiện validate data, nếu như không pass thì Laravel sẽ return về một MassageBag (Illuminate\Support\MessageBag) chứa các error massage. Và Laravel sẽ tự động gán MassageBag vào trong $errors trong views.

Để lấy ra error message đầu tiên của một field các bạn sử dụng phương thức first.

VD: Lấy ra error message lỗi đầu tiên của trường email.

Ví dụ

$errors = $validator->errors();

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

Hoặc trong blade

Ví dụ

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

Để lấy ra tất cả message của một trường nào đó các bạn có thể sử dụng phương thức get. Hàm này sẽ trả về một mảng các message lỗi của trường đó.

VD: In ra tất cả các message lỗi của trường email.

Ví dụ

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

Nếu input của bạn là một mảng, bạn có thể lấy ra tất cả error message trong mảng input key đó bằng cách sử dụng ký tự '*'.

VD: Lấy ra error massage của các attachments.

Ví dụ

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

Còn trong trường hợp bạn muốn lấy ra tất cả các các error message của validator, bạn có thể sử dụng phương thức all.

VD: lấy ra tất cả các error message.

Ví dụ

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

Đôi lúc, bạn sẽ cần kiểm tra xem trường nào đó có tồn tại error message hay không, bạn có thể sử dụng phương thức has. Phương thức này sẽ trả về true nếu trường đó có error message.

VD: Kiểm tra xem validate input email có sai hay không.

Ví dụ

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

Sửa nội dung error message.

Mặc định các message trong Laravel được đặt trong resources/lang/en/validation.php.

Và nếu như bạn muốn thay đổi nội dung message cho một trường nào đó, bạn có thể thêm vào trong key custom.

VD: Thay đổi error mesage cho trường email với rule reqruire và max.

Ví dụ

'custom' => [
    'email' => [
        'required' => 'We need to know your email address!',
        'max' => 'Your email address is too long!'
    ],
],

Tương tự bạn cũng có thể custom attribute trong file language, bằng cách thiết lập trong key attribute.

VD: thay đổi attribute name của trường email.

Ví dụ

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

Các rule có sẵn trong Laravel.

Do Laravel cung cấp rất nhiều rule, nên mình chỉ liệt kê ra một số rule hay dùng thôi. Các bạn có thể xem toàn bộ những rule mà Laravel hỗ trợ sẵn tại đây.

Rule Mô Tả
accepted Rule này chỉ chấp nhận các giá trị"yes","on",1, hoặctrue. Rule này thường được dùng cho các input là radio, checkbox.
active_url Rule này sẽ kiểm tra xem URL này có đang thực sự tồn tại, bằng việc sử dụng hàmdns_get_record trong PHP.
after

Rule này sẽ kiểm tra xem ngày tháng có đang lớn hơn giá trị cần so sánh không.

VD:'start_date' => 'required|date|after:tomorrow'

before Rule này tương tự after nhưng là so sánh nhỏ hơn.
alpha Rule này sẽ kiểm tra xem data gửi lên có phải là các ký tự alphabetic.
alpha_num Rule này sẽ kiểm tra xem dữ liệu có phải là các kí tự alphabetic và số.
array Rule này sẽ kiểm tra xem dữ liệu có phải là array.
bail Rule này sẽ dừng việc validate dữ liệu nếu như có một rule nào đó fail.
between:min,max Rule này sẽ kiểm tra xem giá trị có nằm trong khoảng min, max hay không
confirmed

Rule này sẽ kiểm tra xem dữ liệu có giống với dữ liệu của field_confirmation hay không.

VD: Với trường hợp xác thực password thì nó sẽ kiểm tra xem dữ liệu password_confirmation có trùng với password hay không.

date Kiểm tra xem dữ liệu gửi lên có phải là date không.
dimensions

Rule này sẽ kiểm tra kích thước của ảnh upload lên.

VD:'avatar' => 'dimensions:min_width=100,min_height=200'

email Rule này sẽ kiểm tra xem dữ liệu gửi lên có phải là email.
image Rule này sẽ kiểm tra xem dữ liệu gửi lên có phải image.
in_array:anotherfield Rule này sẽ kiểm tra xem dữ liệu gửi lên có nằm trong mảnganotherfield.
integer Rule này sẽ kiểm tra xem dữ liệu gửi lên có phải số nguyên hay không.
ip Rule này sẽ kiểm tra xem dữ liệu gửi lên có phải là ip.
ipv4 Rule này sẽ kiểm tra xem dữ liệu gửi lên có phải là ipv4.
ipv6 Rule này sẽ kiểm tra xem dữ liệu gửi lên có phải là ipv6.
json Rule này sẽ kiểm tra xem dữ liệu gửi lên có phải là một json string.
max:value Rule này sẽ kiểm tra xem dữ liệu có nhỏ hơn giá trị value.
min:value Rule này sẽ kiểm tra xem dữ liệu có lớn hơn giá trị value.
not_in:foo,bar Rule này sẽ kiểm tra xem dữ liệu gửi lên không nằm trong mảng.
nullable Rule này sẽ cho phép không cần dữ liệu gửi lên.
numberic Rule này sẽ kiểm tra xem dữ liệu gửi lên có phải là numeric hay không.
regex:pattern Rule này sẽ kiểm tra xem dữ liệu phải matching vơi pattern.
required Rule này sẽ bắt buộc trường phải có dữ liệu.
string Rule này sẽ bắt buộc dữ liệu phải là string.
unique:table,column,except,idColumn Rule này sẽ kiểm tra dữ liệu bắt buộc phải chưa xuất hiện với điều kiện ở trong database.
url Rule này bắt buộc dữ liệu gửi lên phải là một URL.

Thêm mới rule trong Laravel.

Nếu như các rule mà Laravel cung cấp không giải quyết được vấn đề của bạn. Bạn có thể tạo mới một rule theo cách của bạn một cách đơn giản bằng cách sử dụng command make:rule. Command này sẽ tạo ra một rule trong app/Rules cho các bạn viết logic vào trong.

VD: Tạo thêm rule Uppercase để kiểm tra xem data có phải đang ở dạng chữ in hoa hay không.

Ví dụ

php artisan make:rule Uppercase

Lúc này file rule sẽ có dạng như sau:

- app/Rules/Uppercase.php

Ví dụ

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        //
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'The validation error message.';
    }
}

Trong đó:

  • Phương thức passes mà trả về true thì rule sẽ được pass và ngược lại.
  • Phương thức massage sẽ trả về message string nếu như rule không pass.

Lúc này khi muốn sử dụng rule vào validator bạn chỉ sử dụng như sau:

Ví dụ

use App\Rules\Uppercase;

$request->validate([
    'name' => ['required', 'string', new Uppercase],
]);

Ngoài cách tạo thêm rule trên, bạn cũng có thể đưa logic vào trong một closure với cú pháp:

Ví dụ

function ($attribute, $value, $fail) {
    if ($value === 'foo') {
        $fail('The '.$attribute.' is invalid.');
    }
}

Trong đó:

  • $attribute là tên của trường cần validate.
  • $value là giá trị của trường cần validate.
  • $fail là một callback function sẽ được gọi khi validate fail.

VD:

Ví dụ

use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'title' => [
        'required',
        'max:255',
        function ($attribute, $value, $fail) {
            if ($value === 'foo') {
                $fail('The '.$attribute.' is invalid.');
            }
        },
    ],
]);

Bài viết này đã giúp ích cho bạn?

Advertisements