8. Tạo trình validation thủ công (ok)

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

Nếu bạn không muốn sử dụng method validate của request, bạn có thể tạo một trình validation thủ công sử dụng Validator facade. Với method make trên facade, nó sẽ tạo một lớp validator.

Chẳng hạn:

use Illuminate\Support\Facades\Validator;

public function store(Request $request)
{
    $validator = Validator::make($input, $rules);
    
    if ($validator->fails()) {
        // Khởi tạo response thủ công
    }
}

Tại method Validator::make:

  • Tham số đầu tiên là mảng các request cần validate.

  • Tham số thứ hai là mảng validation rule.

Khác với method validate thì Validator::make chỉ thực hiện validation nhưng không tự động tạo response để trả về cho người dùng. Vì vậy chúng ta sẽ phải tự khai báo thủ công. Để kiểm tra trạng thái validation ta sử dụng method fails từ object trả về của Validator::make. Từ đó ta thực hiện khởi tạo response, bạn có thể sử dụng hai cách để trả về response:

  1. Redirect response

    Cách này sử dụng khi gửi request qua form truyền thống. Chúng ta có thể sử dụng method withErrors với tham số là $validator để flash các thông báo lỗi tới $errors của blade template. Ngoài ra bạn cũng có thể truyền một object MessageBag hoặc PHP array vào method withErrors.

    return back()->withErrors($validator);

    Bạn có thể thêm method withInput phía sau để flash input.

    return back()->withErrors($validator)->withInput();
  2. JSON response

    Nếu ứng dụng của bạn gửi bằng AJAX thì có thể sử dụng cách này, nhưng ở đây, để lấy các thông báo lỗi từ $validtor, ta phải sử dụng method errors.

    return response()->json($validator->errors(), 422);

Bây giờ bạn có thể áp dụng nó cho ví dụ ở trên. Mình sẽ thử gửi request với AJAX nhé.

Với blade view create_post thì mình sẽ lấy lại đoạn code phần AJAX request & validation.

Tại method store trong controller App\Http\Controllers\PostController các bạn code như sau:

use Illuminate\Support\Facades\Validator;

public function store(Request $request) {
    $validator = Validator::make($request->all(), ['title' => 'required|max:100', 'body' => 'required|min:50']);
    if ($validator->fails()) {
      return response()->json($validator->errors(), 422);
    }
  }

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

Ví dụ đã hoàn thành:

C:\xampp\htdocs\blog\routes\web.php

Route::get('post/create', 'PostController@create');
Route::post('post', 'PostController@store');

C:\xampp\htdocs\blog\app\Http\Controllers\PostController.php

public function create() {
    return view('create_post');
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request) {
    $validator = Validator::make($request->all(), ['title' => 'required|max:100', 'body' => 'required|min:50']);
    if ($validator->fails()) {
      return response()->json($validator->errors(), 422);
    }
  }

C:\xampp\htdocs\blog\app\Http\Requests\StorePost.php

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePost 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 [
      'title' => 'required|max:100',
      'body'  => 'required|min:50',
    ];
  }
  public function withValidator($validator) {
    $validator->after(function ($validator) {
      $validator->errors()->add('field', 'Something is wrong with this field!');
    });
  }
  public function messages() {
    return [
      // 'title.required' => 'Tiêu đề bài viết không được bỏ trống',
      // 'body.required'  => 'Nội dung bài viết không được bỏ trống',
      'required' => ':attribute không được bỏ trống'
    ];
  }
  public function attributes() {
    return [
      'title' => 'Tiêu đề bài viếts',
      'body' => 'Nội dung bài viếts'
    ];
  }
}

C:\xampp\htdocs\blog\resources\views\create_post.blade.php

<h1>Create new post</h1>
<form action="/post" method="POST">
    @csrf
    <div>
        <p>Title</p>
        <input type="text" name="title">
    </div>
    <div>
        <p>Body</p>
        <textarea name="body" cols="30" rows="10"></textarea>
    </div>
    <br>
    <div>
        <button type="submit">Create</button>
    </div>
</form>
<script src="http://localhost/library/jquery/jquery.min.js"></script>
<script>
    $('form').submit(function(e) {
        e.preventDefault();
        $.ajax({
            url: '/post',
            type: 'POST',
            data: {
                _token: $('input[name=_token]').val(),
                title: $('input[name=title]').val(),
                body: $('textarea[name=body]').val()
            }, success: function(res) {
                //
            }, error: function(error) {
                console.log(error);
            }
        })
    })
</script>

1. Tự động chuyển hướng (Automatic redirection)

Nếu như bạn đang khởi tạo một validator thủ công nhưng vẫn muốn sử dụng lợi ích tự động chuyển hướng hoặc trả về JSON response của method validate thì có thể kết nối thêm method validate sau lớp khởi tạo trả về từ Validator::make.

Validator::make($input, $rules)->validate();

2. Đặt tên cho các "túi" lỗi (Named error bags)

Nếu như bạn có nhiều form trên một trang đơn, bạn sẽ muốn đặt tên cho từng lỗi của một form nhất định, từ đó giúp bạn dễ dàng lấy nó từ blade template. Để làm việc này rất đơn giản, bạn chỉ cần việc truyền tham số thứ hai là tên mà bạn cần đặt cho "túi" lỗi tại method withErrors.

withErrors($validator, 'name_error_bag')

Bạn có thể truy cập "túi" lỗi ấy tại blade view như sau:

$errors->name_error_bag->something();

Về một số method để thao tác với "túi" lỗi, mình sẽ ói ở phần bên dưới.

3. After validation hook

Validator cũng cho phép chúng ta thêm after validation hook, bạn cần thực hiện theo thứ sau để có thể hoạt động nó:

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

$validtor->after(function($validator) {
    //
});

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

Last updated