😆Tạo trình validation thủ công (Manually creating validator) Phần 2 (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.

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);

C:\xampp8\htdocs\oec\routes\web.php

<?php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
  return view('welcome');
});
Route::get('post/create', [PostController::class, 'create']);
Route::post('/post', [PostController::class, 'store']);

C:\xampp8\htdocs\plugindev\app\Http\Controllers\PostController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index()
  {
    //
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    return view('posts.create');
  }
  /**
   * 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'
    ]);
    if ($validator->fails()) {
      return response()->json($validator->errors(), 422);
    }
  }
  /**
   * Display the specified resource.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function show($id)
  {
    //
  }
  /**
   * Show the form for editing the specified resource.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function edit($id)
  {
    //
  }
  /**
   * Update the specified resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function update(Request $request, $id)
  {
    //
  }
  /**
   * Remove the specified resource from storage.
   *
   * @param  int  $id
   * @return \Illuminate\Http\Response
   */
  public function destroy($id)
  {
    //
  }
}

C:\xampp8\htdocs\oec\resources\views\posts\create.blade.php

<style>
  .error {
    color: red;
  }
</style>
<h1>Create new post</h1>
<form action="/post" method="POST">
  @csrf
  <div>
    <p @error('title') class="error" @enderror>
      Title
      @error('title')
      : <span>{{ $message }}</span>
      @enderror
    </p>
    <input type="text" name="title">
  </div>
  <div>
    <p @error('body') class="error" @enderror>
      Body
      @error('body')
      : <span>{{ $message }}</span>
      @enderror
    </p>
    <textarea name="body" cols="30" rows="10"></textarea>
  </div>
  <br>
  <div>
    <button type="submit">Create</button>
  </div>
</form>

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

C:\xampp8\htdocs\oec\app\Http\Controllers\PostController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index()
  {
    //
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    return view('posts.create');
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    $messages = [
      'required' => ':attribute không được bỏ trống.'
    ];
    $validator = Validator::make(
      $request->all(), [
      'title' => 'required|max:100',
      'body' => 'required'
      ],
      $messages
    );
    if ($validator->fails()) {
      return response()->json($validator->errors(), 422);
    }
  }
}

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:

C:\xampp8\htdocs\oec\lang\en\validation.php

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

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)

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index()
  {
    //
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    return view('posts.create');
  }
  /**
   * Store a newly created resource in storage.
   *
   * @param  \Illuminate\Http\Request  $request
   * @return \Illuminate\Http\Response
   */
  public function store(Request $request)
  {
    $messages = [
      'title.required' => 'Tiêu đề bài viết không được bỏ trống.'
    ];
    $validator = Validator::make(
      $request->all(), [
      'title' => 'required|max:100',
      'body' => 'required'
      ],
      $messages
    );
    if ($validator->fails()) {
      return response()->json($validator->errors(), 422);
    }
  }
}

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.

C:\xampp8\htdocs\oec\app\Http\Controllers\PostController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index()
  {
    //
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    return view('posts.create');
  }
  /**
   * 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'
      ],
    );
    if ($validator->fails()) {
      return response()->json($validator->errors(), 422);
    }
  }
}

C:\xampp8\htdocs\oec\lang\en\validation.php

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

C:\xampp8\htdocs\oec\config\app.php

'locale' => 'vi',

C:\xampp8\htdocs\oec\lang\vi\validation.php

 'custom' => [
    'attribute-name' => [
      'rule-name' => 'custom-message',
    ],
    'title' => [
      'required' => 'Đang sử dụng ngôn ngữ tiếng Việt. Tiêu đề bài viết không được bỏ trống. 😒'
    ]
  ],

C:\xampp8\htdocs\oec\lang\en\validation.php

<?php
return [
  /*
  |--------------------------------------------------------------------------
  | Validation Language Lines
  |--------------------------------------------------------------------------
  |
  | The following language lines contain the default error messages used by
  | the validator class. Some of these rules have multiple versions such
  | as the size rules. Feel free to tweak each of these messages here.
  |
  */
  'accepted' => 'The :attribute must be accepted.',
  'accepted_if' => 'The :attribute must be accepted when :other is :value.',
  'active_url' => 'The :attribute is not a valid URL.',
  'after' => 'The :attribute must be a date after :date.',
  'after_or_equal' => 'The :attribute must be a date after or equal to :date.',
  'alpha' => 'The :attribute must only contain letters.',
  'alpha_dash' => 'The :attribute must only contain letters, numbers, dashes and underscores.',
  'alpha_num' => 'The :attribute must only contain letters and numbers.',
  'array' => 'The :attribute must be an array.',
  'ascii' => 'The :attribute must only contain single-byte alphanumeric characters and symbols.',
  'before' => 'The :attribute must be a date before :date.',
  'before_or_equal' => 'The :attribute must be a date before or equal to :date.',
  'between' => [
    'array' => 'The :attribute must have between :min and :max items.',
    'file' => 'The :attribute must be between :min and :max kilobytes.',
    'numeric' => 'The :attribute must be between :min and :max.',
    'string' => 'The :attribute must be between :min and :max characters.',
  ],
  'boolean' => 'The :attribute field must be true or false.',
  'confirmed' => 'The :attribute confirmation does not match.',
  'current_password' => 'The password is incorrect.',
  'date' => 'The :attribute is not a valid date.',
  'date_equals' => 'The :attribute must be a date equal to :date.',
  'date_format' => 'The :attribute does not match the format :format.',
  'decimal' => 'The :attribute must have :decimal decimal places.',
  'declined' => 'The :attribute must be declined.',
  'declined_if' => 'The :attribute must be declined when :other is :value.',
  'different' => 'The :attribute and :other must be different.',
  'digits' => 'The :attribute must be :digits digits.',
  'digits_between' => 'The :attribute must be between :min and :max digits.',
  'dimensions' => 'The :attribute has invalid image dimensions.',
  'distinct' => 'The :attribute field has a duplicate value.',
  'doesnt_end_with' => 'The :attribute may not end with one of the following: :values.',
  'doesnt_start_with' => 'The :attribute may not start with one of the following: :values.',
  'email' => 'The :attribute must be a valid email address.',
  'ends_with' => 'The :attribute must end with one of the following: :values.',
  'enum' => 'The selected :attribute is invalid.',
  'exists' => 'The selected :attribute is invalid.',
  'file' => 'The :attribute must be a file.',
  'filled' => 'The :attribute field must have a value.',
  'gt' => [
    'array' => 'The :attribute must have more than :value items.',
    'file' => 'The :attribute must be greater than :value kilobytes.',
    'numeric' => 'The :attribute must be greater than :value.',
    'string' => 'The :attribute must be greater than :value characters.',
  ],
  'gte' => [
    'array' => 'The :attribute must have :value items or more.',
    'file' => 'The :attribute must be greater than or equal to :value kilobytes.',
    'numeric' => 'The :attribute must be greater than or equal to :value.',
    'string' => 'The :attribute must be greater than or equal to :value characters.',
  ],
  'image' => 'The :attribute must be an image.',
  'in' => 'The selected :attribute is invalid.',
  'in_array' => 'The :attribute field does not exist in :other.',
  'integer' => 'The :attribute must be an integer.',
  'ip' => 'The :attribute must be a valid IP address.',
  'ipv4' => 'The :attribute must be a valid IPv4 address.',
  'ipv6' => 'The :attribute must be a valid IPv6 address.',
  'json' => 'The :attribute must be a valid JSON string.',
  'lowercase' => 'The :attribute must be lowercase.',
  'lt' => [
    'array' => 'The :attribute must have less than :value items.',
    'file' => 'The :attribute must be less than :value kilobytes.',
    'numeric' => 'The :attribute must be less than :value.',
    'string' => 'The :attribute must be less than :value characters.',
  ],
  'lte' => [
    'array' => 'The :attribute must not have more than :value items.',
    'file' => 'The :attribute must be less than or equal to :value kilobytes.',
    'numeric' => 'The :attribute must be less than or equal to :value.',
    'string' => 'The :attribute must be less than or equal to :value characters.',
  ],
  'mac_address' => 'The :attribute must be a valid MAC address.',
  'max' => [
    'array' => 'The :attribute must not have more than :max items.',
    'file' => 'The :attribute must not be greater than :max kilobytes.',
    'numeric' => 'The :attribute must not be greater than :max.',
    'string' => 'The :attribute must not be greater than :max characters.',
  ],
  'max_digits' => 'The :attribute must not have more than :max digits.',
  'mimes' => 'The :attribute must be a file of type: :values.',
  'mimetypes' => 'The :attribute must be a file of type: :values.',
  'min' => [
    'array' => 'The :attribute must have at least :min items.',
    'file' => 'The :attribute must be at least :min kilobytes.',
    'numeric' => 'The :attribute must be at least :min.',
    'string' => 'The :attribute must be at least :min characters.',
  ],
  'min_digits' => 'The :attribute must have at least :min digits.',
  'missing' => 'The :attribute field must be missing.',
  'missing_if' => 'The :attribute field must be missing when :other is :value.',
  'missing_unless' => 'The :attribute field must be missing unless :other is :value.',
  'missing_with' => 'The :attribute field must be missing when :values is present.',
  'missing_with_all' => 'The :attribute field must be missing when :values are present.',
  'multiple_of' => 'The :attribute must be a multiple of :value.',
  'not_in' => 'The selected :attribute is invalid.',
  'not_regex' => 'The :attribute format is invalid.',
  'numeric' => 'The :attribute must be a number.',
  'password' => [
    'letters' => 'The :attribute must contain at least one letter.',
    'mixed' => 'The :attribute must contain at least one uppercase and one lowercase letter.',
    'numbers' => 'The :attribute must contain at least one number.',
    'symbols' => 'The :attribute must contain at least one symbol.',
    'uncompromised' => 'The given :attribute has appeared in a data leak. Please choose a different :attribute.',
  ],
  'present' => 'The :attribute field must be present.',
  'prohibited' => 'The :attribute field is prohibited.',
  'prohibited_if' => 'The :attribute field is prohibited when :other is :value.',
  'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.',
  'prohibits' => 'The :attribute field prohibits :other from being present.',
  'regex' => 'The :attribute format is invalid.',
  'required_array_keys' => 'The :attribute field must contain entries for: :values.',
  'required_if' => 'The :attribute field is required when :other is :value.',
  'required_if_accepted' => 'The :attribute field is required when :other is accepted.',
  'required_unless' => 'The :attribute field is required unless :other is in :values.',
  'required_with' => 'The :attribute field is required when :values is present.',
  'required_with_all' => 'The :attribute field is required when :values are present.',
  'required_without' => 'The :attribute field is required when :values is not present.',
  'required_without_all' => 'The :attribute field is required when none of :values are present.',
  'same' => 'The :attribute and :other must match.',
  'size' => [
    'array' => 'The :attribute must contain :size items.',
    'file' => 'The :attribute must be :size kilobytes.',
    'numeric' => 'The :attribute must be :size.',
    'string' => 'The :attribute must be :size characters.',
  ],
  'starts_with' => 'The :attribute must start with one of the following: :values.',
  'string' => 'The :attribute must be a string.',
  'timezone' => 'The :attribute must be a valid timezone.',
  'unique' => 'The :attribute has already been taken.',
  'uploaded' => 'The :attribute failed to upload.',
  'uppercase' => 'The :attribute must be uppercase.',
  'url' => 'The :attribute must be a valid URL.',
  'ulid' => 'The :attribute must be a valid ULID.',
  'uuid' => 'The :attribute must be a valid UUID.',
  'required' => 'The :attribute field is required.',
  /*
  |--------------------------------------------------------------------------
  | Custom Validation Language Lines
  |--------------------------------------------------------------------------
  |
  | Here you may specify custom validation messages for attributes using the
  | convention "attribute.rule" to name the lines. This makes it quick to
  | specify a specific custom language line for a given attribute rule.
  |
  */
  'custom' => [
    'attribute-name' => [
      'rule-name' => 'custom-message',
    ]
  ],
  /*
  |--------------------------------------------------------------------------
  | Custom Validation Attributes
  |--------------------------------------------------------------------------
  |
  | The following language lines are used to swap our attribute placeholder
  | with something more reader friendly such as "E-Mail Address" instead
  | of "email". This simply helps us make our message more expressive.
  |
  */
  'attributes' => [
    'title' => 'Thuộc tính :)'
  ],
];

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

C:\xampp8\htdocs\oec\routes\web.php

<?php
use App\Http\Controllers\PostController;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/
Route::get('/', function () {
  return view('welcome');
});
Route::get('payment', [PostController::class, 'show']);
Route::post('payment', [PostController::class, 'pay']);

C:\xampp8\htdocs\oec\app\Http\Controllers\PostController.php

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
class PostController extends Controller
{
  /**
   * Display a listing of the resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function index()
  {
    //
  }
  /**
   * Show the form for creating a new resource.
   *
   * @return \Illuminate\Http\Response
   */
  public function create()
  {
    return view('posts.create');
  }
  /**
   * 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'
      ],
    );
    if ($validator->fails()) {
      return response()->json($validator->errors(), 422);
    }
  }
  public function show(Request $request)
  {
    return view('payment');
  }
  public function pay(Request $request)
  {
    $request->validate([
      'credit_card_number' => 'required_if:payment_type,cc'
    ]);
    return 'Payment success!';
  }
}

C:\xampp8\htdocs\oec\lang\en\validation.php

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

Kết quả:

Last updated