Validation
16487

# Laravel Validation

Laravel cung cấp một hệ thống kiểm tra dữ liệu mạnh mẽ và dễ sử dụng. Bạn có thể thực hiện kiểm tra dữ liệu (validation) trong các controller, form request, hoặc thậm chí là trực tiếp trong các model. Dưới đây là hướng dẫn cơ bản về cách sử dụng hệ thống kiểm tra dữ liệu của Laravel.

1. Validation trong Controller

Bạn có thể thực hiện kiểm tra dữ liệu trực tiếp trong các phương thức của controller bằng cách sử dụng phương thức validate:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'name' => 'required|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:8|confirmed',
        ]);

        // Nếu dữ liệu hợp lệ, bạn có thể tiếp tục xử lý dữ liệu ở đây.
        // User::create($validatedData);

        return response('User created successfully.');
    }
}
  • name phải có giá trị và không được vượt quá 255 ký tự.
  • email phải là một địa chỉ email hợp lệ và duy nhất trong bảng users.
  • password phải có ít nhất 8 ký tự và được xác nhận (có một trường password_confirmation khớp với password).

2. Validation trong Form Request

Bạn có thể tách logic kiểm tra dữ liệu ra khỏi controller bằng cách sử dụng Form Request. Điều này giúp mã nguồn của bạn sạch hơn và dễ bảo trì hơn.

Tạo một Form Request:

php artisan make:request StoreUserRequest

Sử dụng Form Request:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreUserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:8|confirmed',
        ];
    }
}

Sử dụng Form Request trong Controller:

namespace App\Http\Controllers;

use App\Http\Requests\StoreUserRequest;

class UserController extends Controller
{
    public function store(StoreUserRequest $request)
    {
        $validatedData = $request->validated();

        // Nếu dữ liệu hợp lệ, bạn có thể tiếp tục xử lý dữ liệu ở đây.
        // User::create($validatedData);

        return response('User created successfully.');
    }
}

3. Custom Messages

Bạn có thể tùy chỉnh các thông báo lỗi kiểm tra dữ liệu bằng cách sử dụng phương thức messages trong Form Request hoặc bằng cách truyền mảng thứ ba vào phương thức validate.

Tùy chỉnh thông báo lỗi trong Form Request:
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreUserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'required|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:8|confirmed',
        ];
    }

    public function messages()
    {
        return [
            'name.required' => 'Vui lòng nhập tên.',
            'email.required' => 'Vui lòng nhập địa chỉ email.',
            'email.email' => 'Địa chỉ email không hợp lệ.',
            'email.unique' => 'Địa chỉ email đã tồn tại.',
            'password.required' => 'Vui lòng nhập mật khẩu.',
            'password.min' => 'Mật khẩu phải có ít nhất 8 ký tự.',
            'password.confirmed' => 'Xác nhận mật khẩu không khớp.',
        ];
    }
}

Tùy chỉnh thông báo lỗi trong Controller:

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'name' => 'required|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:8|confirmed',
        ], [
            'name.required' => 'Vui lòng nhập tên.',
            'email.required' => 'Vui lòng nhập địa chỉ email.',
            'email.email' => 'Địa chỉ email không hợp lệ.',
            'email.unique' => 'Địa chỉ email đã tồn tại.',
            'password.required' => 'Vui lòng nhập mật khẩu.',
            'password.min' => 'Mật khẩu phải có ít nhất 8 ký tự.',
            'password.confirmed' => 'Xác nhận mật khẩu không khớp.',
        ]);

        // Nếu dữ liệu hợp lệ, bạn có thể tiếp tục xử lý dữ liệu ở đây.
        // User::create($validatedData);

        return response('User created successfully.');
    }
}

4. Custom Validation Rules

Bạn có thể tạo các quy tắc kiểm tra dữ liệu tùy chỉnh nếu cần.

Tạo Custom Validation Rule:
php artisan make:rule Uppercase

Sử dụng Custom Validation Rule:

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class Uppercase implements Rule
{
    public function passes($attribute, $value)
    {
        return strtoupper($value) === $value;
    }

    public function message()
    {
        return 'The :attribute must be uppercase.';
    }
}

Sử dụng Custom Validation Rule trong Controller hoặc Form Request:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use App\Rules\Uppercase;

class StoreUserRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => ['required', 'max:255', new Uppercase],
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:8|confirmed',
        ];
    }
}

# ValidateWithBag

Trong Laravel, khi thực hiện kiểm tra dữ liệu (validation), đôi khi bạn muốn tách biệt các thông báo lỗi thành nhiều túi (bag) khác nhau. Điều này có thể hữu ích khi bạn có nhiều form trên cùng một trang và bạn muốn quản lý thông báo lỗi riêng biệt cho từng form. Laravel cung cấp phương thức validateWithBag để thực hiện điều này.

Sử dụng validateWithBag

Phương thức validateWithBag cho phép bạn chỉ định một túi lỗi cụ thể cho các lỗi kiểm tra dữ liệu. Đây là cách sử dụng cơ bản:

Controller:

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    public function store(Request $request)
    {
        $validatedData = $request->validateWithBag('storeUser', [
            'name' => 'required|max:255',
            'email' => 'required|email|unique:users,email',
            'password' => 'required|min:8|confirmed',
        ]);

        // Nếu dữ liệu hợp lệ, bạn có thể tiếp tục xử lý dữ liệu ở đây.
        // User::create($validatedData);

        return response('User created successfully.');
    }

    public function update(Request $request, $id)
    {
        $validatedData = $request->validateWithBag('updateUser', [
            'name' => 'required|max:255',
            'email' => 'required|email|unique:users,email,' . $id,
        ]);

        // Nếu dữ liệu hợp lệ, bạn có thể tiếp tục xử lý dữ liệu ở đây.
        // User::find($id)->update($validatedData);

        return response('User updated successfully.');
    }
}

Trong ví dụ trên, phương thức validateWithBag được sử dụng với túi lỗi storeUser cho phương thức store và túi lỗi updateUser cho phương thức update.

Hiển thị lỗi trong Blade

Để hiển thị các thông báo lỗi cho từng túi lỗi riêng biệt trong Blade, bạn có thể sử dụng phương thức hasBaggetBag của đối tượng $errors.

Ví dụ trong Blade template:
<!-- Form tạo người dùng mới -->
<form action="{{ route('user.store') }}" method="POST">
    @csrf
    <div>
        <label for="name">Name</label>
        <input type="text" id="name" name="name">
        @if ($errors->storeUser->has('name'))
            <div>{{ $errors->storeUser->first('name') }}</div>
        @endif
    </div>
    <div>
        <label for="email">Email</label>
        <input type="email" id="email" name="email">
        @if ($errors->storeUser->has('email'))
            <div>{{ $errors->storeUser->first('email') }}</div>
        @endif
    </div>
    <div>
        <label for="password">Password</label>
        <input type="password" id="password" name="password">
        @if ($errors->storeUser->has('password'))
            <div>{{ $errors->storeUser->first('password') }}</div>
        @endif
    </div>
    <button type="submit">Create User</button>
</form>

<!-- Form cập nhật người dùng -->
<form action="{{ route('user.update', ['id' => 1]) }}" method="POST">
    @csrf
    @method('PUT')
    <div>
        <label for="name">Name</label>
        <input type="text" id="name" name="name">
        @if ($errors->updateUser->has('name'))
            <div>{{ $errors->updateUser->first('name') }}</div>
        @endif
    </div>
    <div>
        <label for="email">Email</label>
        <input type="email" id="email" name="email">
        @if ($errors->updateUser->has('email'))
            <div>{{ $errors->updateUser->first('email') }}</div>
        @endif
    </div>
    <button type="submit">Update User</button>
</form>

Trong ví dụ trên, các thông báo lỗi cho từng form được hiển thị riêng biệt dựa trên túi lỗi tương ứng (storeUserupdateUser).

Kết luận

Phương thức validateWithBag của Laravel giúp bạn dễ dàng tách biệt và quản lý các thông báo lỗi cho nhiều form trên cùng một trang. Bằng cách sử dụng túi lỗi riêng biệt, bạn có thể đảm bảo rằng mỗi form chỉ hiển thị các thông báo lỗi liên quan, giúp giao diện người dùng trở nên rõ ràng và dễ hiểu hơn.

# Dừng Lại Khi Gặp Lỗi Đầu Tiên

Trong Laravel, để dừng kiểm tra dữ liệu khi gặp lỗi đầu tiên, bạn có thể sử dụng quy tắc bail. Quy tắc này sẽ yêu cầu Laravel dừng quá trình kiểm tra dữ liệu đối với thuộc tính cụ thể ngay khi phát hiện ra lỗi đầu tiên.

Sử Dụng Quy Tắc bail

Bạn có thể gán quy tắc bail cho thuộc tính cần kiểm tra. Khi một thuộc tính có quy tắc bail và Laravel phát hiện ra lỗi đầu tiên trên thuộc tính đó, các quy tắc kiểm tra còn lại sẽ không được thực thi.

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

Ngoài ra, bạn có thể sử dụng method stopOnFirstFailure 

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

# Lưu Ý Về Các Thuộc Tính Lồng Nhau

Trong Laravel, khi yêu cầu HTTP chứa dữ liệu trường "lồng nhau", bạn có thể chỉ định các trường này trong các quy tắc kiểm tra dữ liệu (validation rules) bằng cú pháp "dot". Ngoài ra, nếu tên trường của bạn chứa một dấu chấm thực sự, bạn có thể ngăn chặn việc này bị hiểu sai thành cú pháp "dot" bằng cách sử dụng dấu gạch chéo ngược để thoát khỏi dấu chấm.

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class PostController extends Controller
{
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'title' => 'required|unique:posts|max:255',
            'author.name' => 'required',
            'author.description' => 'required',
        ]);

        // Nếu dữ liệu hợp lệ, bạn có thể tiếp tục xử lý dữ liệu ở đây.
        // Post::create($validatedData);

        return response('Post created successfully.');
    }
}
  • title là một trường thông thường với các quy tắc required, unique:posts, và max:255.
  • author.nameauthor.description là các thuộc tính lồng nhau trong trường author.

Tránh Nhầm Lẫn Với Tên Trường Chứa Dấu Chấm Thực Sự

Nếu tên trường của bạn chứa một dấu chấm thực sự, bạn có thể ngăn chặn việc này bị hiểu sai thành cú pháp "dot" bằng cách sử dụng dấu gạch chéo ngược để thoát khỏi dấu chấm. Điều này hữu ích khi bạn có các phiên bản hoặc các tên trường đặc biệt.

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class VersionController extends Controller
{
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'title' => 'required|unique:posts|max:255',
            'v1\.0' => 'required',
        ]);

        // Nếu dữ liệu hợp lệ, bạn có thể tiếp tục xử lý dữ liệu ở đây.
        // Version::create($validatedData);

        return response('Version created successfully.');
    }
}
  • title là một trường thông thường với các quy tắc required, unique:posts, và max:255.
  • v1\.0 là một tên trường chứa dấu chấm thực sự và được thoát bằng dấu gạch chéo ngược.

Tham khảo
# Available Validation Rules

# Tái Tạo Dữ Liệu Cho Form

Trong Laravel, việc tái tạo dữ liệu cho các form rất quan trọng để giữ lại thông tin đã nhập vào khi có lỗi xảy ra hoặc khi cần hiển thị lại dữ liệu đã lưu trước đó. Laravel cung cấp nhiều cách để thực hiện việc này một cách dễ dàng và hiệu quả.

Sử Dụng old() Helper

Khi một yêu cầu HTTP POST không thành công do lỗi kiểm tra dữ liệu, Laravel sẽ tự động chuyển hướng người dùng trở lại trang trước đó với dữ liệu cũ (old input) và các thông báo lỗi. Bạn có thể sử dụng helper old() để lấy lại dữ liệu này và hiển thị trong form.

<form action="{{ route('post.store') }}" method="POST">
    @csrf
    <div>
        <label for="title">Title</label>
        <input type="text" id="title" name="title" value="{{ old('title') }}">
        @error('title')
            <div class="error">{{ $message }}</div>
        @enderror
    </div>
    <div>
        <label for="content">Content</label>
        <textarea id="content" name="content">{{ old('content') }}</textarea>
        @error('content')
            <div class="error">{{ $message }}</div>
        @enderror
    </div>
    <button type="submit">Submit</button>
</form>

Trong ví dụ này, nếu kiểm tra dữ liệu không thành công, giá trị của các trường titlecontent sẽ được tái tạo lại trong form bằng cách sử dụng old('title')old('content').

Danh mục


  1. Khác
  2. ThreeJS
  3. Ubuntu/Linux
  4. HTML/CSS
  5. Git
  6. Amazon Web Services
  7. Javascript
  8. Docker
  9. Laravel

Bài viết liên quan


Routing

Routing

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về Basic Routing trong Laravel, từ cách định nghĩa route, sử dụng middleware, route caching đến route naming giúp tối ưu hóa ứng dụng.
Blade Basics

Blade Basics

01.08.2024
Author: ADMIN
Khám phá Blade trong Laravel: từ if-else, loops, kế thừa layout đến include sub-views. Giúp code gọn gàng, dễ quản lý và bảo trì hơn!
Hiển thị giá trị trong Blade

Hiển thị giá trị trong Blade

01.08.2024
Author: ADMIN
Hướng dẫn hiển thị biến trong Laravel Blade: escape HTML tự động, hiển thị dữ liệu thô, giá trị mặc định và cách truy xuất mảng, đối tượng. Giúp bạn tối ưu hiển thị dữ liệu một cách an toàn!
Layout: @include, @extends, @section, @yield

Layout: @include, @extends, @section, @yield

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về @include, @extends, @section và @yield trong Laravel Blade. Tối ưu hóa tái sử dụng giao diện, tổ chức mã rõ ràng, giúp phát triển và bảo trì ứng dụng dễ dàng hơn!

Bài viết khác

Routing

Routing

01.08.2024
Author: ADMIN
Hướng dẫn chi tiết về Basic Routing trong Laravel, từ cách định nghĩa route, sử dụng middleware, route caching đến route naming giúp tối ưu hóa ứng dụng.
Blade Basics

Blade Basics

01.08.2024
Author: ADMIN
Khám phá Blade trong Laravel: từ if-else, loops, kế thừa layout đến include sub-views. Giúp code gọn gàng, dễ quản lý và bảo trì hơn!
9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

9 Mẹo Hữu Ích Khi Sử Dụng Blade Trong Laravel

01.08.2024
Author: ADMIN
Khám phá 9 mẹo Blade giúp bạn viết code Laravel sạch, tối ưu và chuyên nghiệp hơn. Từ @forelse, @auth, @guest, đến format ngày, tối ưu SEO – tất cả trong một bài viết súc tích, dễ áp dụng!
Hiển thị giá trị trong Blade

Hiển thị giá trị trong Blade

01.08.2024
Author: ADMIN
Hướng dẫn hiển thị biến trong Laravel Blade: escape HTML tự động, hiển thị dữ liệu thô, giá trị mặc định và cách truy xuất mảng, đối tượng. Giúp bạn tối ưu hiển thị dữ liệu một cách an toàn!