# Tạo trình validation thủ công (Manually creating validator) Phần 2 (ok)

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.

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

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

<figure><img src="/files/6CPCoozc71ZNowujr1it" alt=""><figcaption></figcaption></figure>

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

```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
<?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) <a href="#id-5-tuy-chinh-thong-bao-loi-customizing-error-message-26" id="id-5-tuy-chinh-thong-bao-loi-customizing-error-message-26"></a>

<figure><img src="/files/owJ68JQrlAEY8wLAYL7t" alt=""><figcaption></figcaption></figure>

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

```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

```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) <a href="#a-chi-dinh-mot-thong-bao-tuy-chinh-cho-mot-thuoc-tinh-nhat-dinh-specifying-a-custom-message-for-a-g" id="a-chi-dinh-mot-thong-bao-tuy-chinh-cho-mot-thuoc-tinh-nhat-dinh-specifying-a-custom-message-for-a-g"></a>

<figure><img src="/files/QZECNy5Q46qFJ55LIHE4" alt=""><figcaption></figcaption></figure>

```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 = [
      '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) <a href="#b-chi-dinh-thong-bao-tuy-chinh-trong-tep-ngon-ngu-specifying-custom-message-in-language-file-28" id="b-chi-dinh-thong-bao-tuy-chinh-trong-tep-ngon-ngu-specifying-custom-message-in-language-file-28"></a>

**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`.

<figure><img src="/files/ngh6ovm8gEHz2p94CXKh" alt=""><figcaption></figcaption></figure>

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

```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

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

<figure><img src="/files/DlaD7bOSjGyVymqKzbft" alt=""><figcaption></figcaption></figure>

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

```php
'locale' => 'vi',
```

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

```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. 😒'
    ]
  ],
```

<figure><img src="/files/eItBX3jPeIkTAFLEGREd" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/S5ddOCPOIMxu7Wk8oLFX" alt=""><figcaption></figcaption></figure>

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

```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 :)'
  ],
];

```

### &#x20;Chỉ định giá trị tùy chỉnh trong tệp ngôn ngữ (Specifying custom value in language file) <a href="#d-chi-dinh-gia-tri-tuy-chinh-trong-tep-ngon-ngu-specifying-custom-value-in-language-file-30" id="d-chi-dinh-gia-tri-tuy-chinh-trong-tep-ngon-ngu-specifying-custom-value-in-language-file-30"></a>

<figure><img src="/files/OVJbEs0ACP1IBUSc36xq" alt=""><figcaption></figcaption></figure>

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

```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
<?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!';
  }
}

```

<figure><img src="/files/VOFHujlHedsQKhfC0EZK" alt=""><figcaption></figcaption></figure>

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

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

Kết quả:&#x20;

<figure><img src="/files/LvLybMhZRU9F6IKOcgZ7" alt=""><figcaption></figcaption></figure>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://learnphp.gitbook.io/learnphp/learn-lavarel/tao-trinh-validation-thu-cong-manually-creating-validator-phan-2-ok.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
