Laravel Validation ขั้นพื้นฐาน มีอะไรบ้าง

1 กุมภาพันธ์ 2564 เวลาอ่าน 10 นาที
Laravel Validation ขั้นพื้นฐาน มีอะไรบ้าง

สิ่งสำคัญอย่างนึงในการพัฒนาโปรเจคใน Laravel คือการรู้ว่าเราจะทำการ validate ข้อมูลที่ผู้ใช้ป้อนเข้ามาได้อย่างไรบ้าง Laravel รองรับวิธีการทำ validation ได้หลายแบบในบทความนี้เราจะมาดูวิธีการทำ validation ใน Controller, Form Request และ Rule

Validation ใน Controller

โดยปกติแล้ว Controller ใน Laravel สืบทอดมาจาก Base Controller ที่มีการใช้งาน trait ValidatesRequests

Trait ValidatesRequests ทำให้เราสามารถเรียกใช้ method validate() ใน Controller ได้โดยตรง

ตัวอย่างเช่น ผู้ใช้กำลังจะเพิ่มบทความ Article เข้ามาในระบบใน form อาจมีการระบุชื่อ เนื้อหา และวันที่เผยแพร่ การทำ validation ใน controller จะเขียนแบบใดก็ได้ตามตัวอย่างนี้

 

// ระบุ validation rules แบบ String โดยใช้ | คั่น
public function store(Request $request) {
    $request->validate([
        'name' => 'required|string',
        'body' => 'required|string',
        'publish_at' => 'required|date_format:Y-m-d H:i:s'
    ]);

    // ...
}

// ระบุ validation rules แบบ array
public function store(Request $request) {
    // Note: the array syntax is also available
    $request->validate([
      'name' => ['required', 'string'],
      'body' => ['required', 'string'],
      'publish_at' => ['required', 'date_format:Y-m-d H:i:s'],
    ]);

    // ...
}

// ใช้ request() helper function แทนการ Inject $request
public function store() {
    request()->validate([
      // Validation Rules...
    ]);

    // ...
}

// ใช้ method validate() ใน controller โดยตรง
public function store() {
    $this->validate(request(), [
      // Validation Rules...
    ]);

    // ...
}

 ข้อสังเกตอย่างหนึ่งคือ ค่าที่ return มาจาก method validate() จะเป็นข้อมูลที่ถูก validate ออกมาเท่านั้น

public function store(Request $request) {
    $validatedData = $request->validate([
      'name' => ['required', 'string'],
      'body' => ['required', 'string'],
      'publish_at' => ['required', 'date_format:Y-m-d H:i:s'],
    ]);

    // ['name' => ..., 'body' => ..., 'publish_at' => ...]
    $this->articleService->store($validatedData);
}

อีกวิธีหนึ่ง เราสามารถเขียนแบบนี้ได้

public function store(Request $request) {
    $request->validate([
      'name' => ['required', 'string'],
      'body' => ['required', 'string'],
      'publish_at' => ['required', 'date_format:Y-m-d H:i:s'],
    ]);

    // I know that the only keys in validated data are the ones that were successfully validated, i.e.: name, body, published_at
    $this->articleService->store($request->only('name', 'body', 'published_at'));
}

Validation rules ทั้งหมด ที่มากับ Laravel สามารถดูได้ที่  Laravel document

Validation ใน Form Request

ถ้า Logic การทำ Validation เริ่มมีความซับซ้อน เราควรแยกการทำ validation ออกจาก Controller โดยเราสามารถทำการ validation ได้ผ่านทางคลาส Form Request

เราสามารถใช้ Artisan command เพิ่มสร้างคลาส Form Request ให้เราได้ ตามตัวอย่างคำสั่งนี้

php artisan make:request StoreArticleRequest

คลาสที่ถูกสร้างาขึ้นจะอยู่ใน app/Http/Requests 

class StoreArticleRequest extends FormRequest
{

    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            //
        ];
    }
}

คลาส Form request จะมาพร้อมกับ 2 method คือ  authorize และ rules.

authorize()

method authorize() จะป้องกันการ run code ใน controller ถ้า method นี้ return false Laravel จะ throw 401 unauthorized exception

ตัวอย่างการทำ authorize อาจเป็นประมาณนี้

public function authorize()
{
    return $this->user()->can('create', Article::class);
}

rules()

เราสามารถทำการระบุ array ของ field ที่เราต้องการทำ validation ได้ใน method rules() วิธีการระบุสามารถระบุได้เหมือนกับที่เราระบุใน Controller

public function rules()
{
    return [
      'name' => ['required', 'string'],
      'body' => ['required', 'string'],
      'publish_at' => ['required', 'date_format:Y-m-d H:i:s'],
    ];
}

หมายเหตุ: เราสามารถทำการ Type-hint คลาส dependency ที่เราต้องการใช้ใน method rules() ได้

ทีนี้เราสามารถใช้คลาส Form Request ที่เราสร้างขึ้นใน controller ได้ด้วยการ Type-hint ใน method

public function store(StoreArticleRequest $request) {
    // Validation and Rules passed
}

ถ้า validation fail ผู้ใช้จะถูก redirect พร้อมข้อมูล error flash ลง session ถ้าเป็น AJAX request จะเป็น Response status 422 Unprocessable Entity

เราสามารถใช้ข้อมูลที่ validate มาได้เหมือนก่อนหน้านี้

public function store(StoreArticleRequest $request) {
    $validatedData = $request->validated();

    // Insert into database
    ...
}

สร้างคลาส Custom Rule

ถ้าเราต้องการทำ Validation ที่ไม่มีมาพร้อมกับ Laravel เราสามารถสร้าง คลาส Validation Rule ขึ้นมาใหม่ได้

เราสามารถสร้างคลาส Rule ได้โดยช้ Artisan command

php artisan make:rule IsValidStateInUSA

คลาส Rule ที่ถูกสร้างขึ้นจะอยู่ใน app/Rules

class IsValidStateInUSA implements Rule
{

    public function passes($attribute, $value)
    {
        //
    }

    public function message()
    {
        return 'The validation error message.';
    }
}

เราสามารถระบุ code เพื่อทำการตรวจสอบ validation ได้ใน method passes() โดย return true ถ้าผ่านการ validation ส่วน method message() ไว้ทำการแสดงข้อความกรณีที่ validation fail

 

ใช้ตัวอย่างจากคลาส Is a valid State in the USA, เราอาจเขียน code ออกมาได้หน้าตาประมาณนี้

class IsValidStateInUSA implements Rule
{

    public function passes($attribute, $value)
    {
        return in_array(strtoupper($value), [
          'AL',
          'AK',
          'AZ',
          ...
        ]);
    }

    public function message()
    {
        return 'This is not a valid state code in the USA.';
    }
}

 

วิธีการใช้งานคลาส Validation Rule ที่เราสร้างขึ้นสามารถทำได้โดยการ new คลาสขึ้นมา ใน array ของ rule ที่เราต้องการ validate ใน field ที่กำหนด

public function store(Request $request) {
    $request->validate([
      'state' => ['required', new IsValidStateInUSA],
    ]);

    ...
}

การจัดการกับ Validation Error

Laravel จะทำการ redirect ให้เราโดยอัตโนมัติถ้ามีการ fail validation โดยจะมีตัวแปร $errors ที่ถูกส่งให้ view ทุกครั้งอยู่แล้ว

เราสามารถสร้าง blade view messages.blade.php แล้ว include ใน layout ของเรา เพื่อแสดง validation error message ได้

@if($errors->any())
    <div class="alert alert-danger" role="alert">
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
            <span aria-hidden="true">×</span>
        </button>

        @foreach($errors->all() as $error)
            {{ $error }}<br/>
        @endforeach
    </div>
@endif

ซึ่งจะแสดง error ทั้งหมดที่เก็บใน session ถ้าเราต้องการแสดง error ทีละ field เราะสามารถใช้ helper @error ช่วยได้

@error('title')
    <div class="alert alert-danger">{{ $message }}</div>
@enderror

ใน @error tag จะมีตัวแปร $message ให้เราใช้งานได้โดยอัตโนมัติ

การแก้ไขข้อความ Error

เวลาที่เราทำงานกับ method validate() เราสามารถ override ข้อความ error ได้โดยการส่ง parameter ตัวที่สาม

public function store(Request $request) {
    $this->validate($request, [
        'name' => 'required|string',
        'body' => 'required|string',
        'publish_at' => 'required|date_format:Y-m-d H:i:s'
    ], [
      'name.required' => 'A article name is required',
      'body.required'  => 'A article body is required',
      'publish_at.date_format' => 'The publish at date is not in the correct format.'
    ]);

    // ...
}

ถ้าเป็นกรณี Form Request เราสามารถใช้ method messages() เพื่อ override ข้อความ error ในแต่ละ field และแต่ละ rule ได้เช่นเดียวกัน

public function messages()
{
    return [
        'name.required' => 'A article name is required',
        'body.required'  => 'A article body is required',
        'publish_at.date_format' => 'The publish at date is not in the correct format.'
    ];
}

สรุป

จากบทความนี้เราได้เรียนรู้ถึงวิธีการทำ Validation แบบต่าง ๆ ใน Laravel ตั้งแต่วิธีพื้นฐานสุดคือการ validate ใน Controller เราได้รู้จักการสร้างคลาส Form Request สำหรับ validation ที่ซับซ้อนขึ้น การสร้าง Customer Validation Rule สำหรับ logic การทำ validation ที่เราต้องการกำหนดขึ้นมาเอง รวมไปถึงการแก้ไขข้อความ error ถ้าเราอยากเรียนรู้เรื่องการทำ Validation ใน Laravel ให้มากขึ้น ลองศึกษาเพิ่มเติมได้จากใน Laravel Documentation

Phattarachai Chaimongkol

เกี่ยวกับ phattarachai.dev

ผมอ๊อฟนะครับ เป็นผู้ประกอบการอิสระ ที่ปรึกษาทางด้าน Web Application Development ให้แก่องค์กร ธุรกิจ SME และหน่วยงานราชการ
Web Developer ผู้มีใจรักใน Laravel เป็นพาร์ทเนอร์บริษัท Digital Agency ชั้นนำทางด้าน UX/UI เพื่อพัฒนาโปรเจคให้แก่ลูกค้า ผมช่วยสร้างเครื่องมือทางด้าน Web ที่มีคุณภาพให้ผู้ประกอบการดำเนินธุรกิจได้ง่ายขึ้นใช้งานได้จริง เน้นประสบการณ์ ความชำนาญ ผลงานคุ้มค่าเทียบเท่าจ้างงานกับบริษัทใหญ่ ๆ

ยามว่าง ๆ ชอบเล่นเกมส์บน Steam ครับ

เรื่องที่เกี่ยวข้อง

PHP function แสดงขนาดไฟล์แบบคนอ่านรู้เรื่อง เป็น KB, MB, GB
1 กุมภาพันธ์ 2564
PHP function แสดงขนาดไฟล์แบบคนอ่านรู้เรื่อง เป็น KB, MB, GB
คำสั่ง Postgresql ที่เอาไว้ใช้จัดการเกี่ยวกับ Replication
1 กุมภาพันธ์ 2564
คำสั่ง Postgresql ที่เอาไว้ใช้จัดการเกี่ยวกับ Replication
สรุป Taylor Otwell Keynote ใน Laracon US 2024 - Inertia 2.0, VS Code Extension และ Laravel Cloud
1 กุมภาพันธ์ 2564
สรุป Taylor Otwell Keynote ใน Laracon US 2024 - Inertia 2.0, VS Code Extension และ Laravel Cloud