Laravel 7 : สร้างฟอร์มเพิ่มข้อมูล

หลังจากเรียนรู้วิธีการใช้ Model เพิ่ม อ่าน แก้ไข และลบข้อมูลลงบนฐานข้อมูลโดยผ่านการใช้ tinker ได้แล้ว ในตอนนี้ลองมาสร้างเว็บฟอร์ม เพื่อใช้กรอกข้อมูลผ่านหน้าเว็บแล้วไปเรียกใช้ Model เพื่อบันทึกลงบนฐานข้อมูลกัน

เพื่อให้ผู้อ่านเข้าใจกระบวนการของ Laravel จะขอเพิ่มโปรแกรมทีละส่วน แล้วดู error ที่เกิดขึ้น พร้อมอธิบายการแก้ไข โดยจะใช้รูปแบบการกำหนด url การสร้างไฟล์ ตั้งชื่อคลาส หรือเมธอด แบบที่ทางเว็บไซต์ Laravel หรือ Laracasts แนะนำ

เริ่มต้นแก้ไขไฟล์ routes/web.php เพิ่ม url articles/create สำหรับเพิ่มข้อมูล articles โดยเมื่อมีการเรียกใช้งาน url นี้ ต้องส่งไปประมวลผลที่คลาส ArticleController ชื่อเมธอด create

ตัวอย่างการแก้ไขไฟล์ routes/web.php เพื่อเพิ่ม url articles/create

// routes/web.php
...
Route::get('articles/create', 'ArticleController@create');

รันคำสั่ง artisan ระบุ make:controller ตามด้วยชื่อคลาส ArticleController ที่เราต้องการสร้าง

$ php artisan make:controller ArticleController
Controller created successfully.

แก้ไขไฟล์ ArticleController.php เพิ่มเมธอด create โดยจะไปเรียกส่วน view ชื่อไฟล์ articles.create มาแสดงผล

// app/Http/Controllers/ArticleController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ArticleController extends Controller
{
    public function create()
    {
        return view('articles.create');
    }
}

สร้างโฟลเดอร์สำหรับไฟล์ view ต่างๆ ของ articles

$ mkdir resources/views/articles

สร้างไฟล์ resources/views/articles/create.blade.php เพื่อแสดงเว็บฟอร์มเพิ่มข้อมูล

Article create form

ถ้าสร้างไฟล์ต่างๆ ถูกต้อง ทดลองใช้คำสั่ง curl หรือ browser จะได้ผลลัพธ์ Article create from

$ curl http://blog.test/articles/create
Article create form

ก่อนหน้านี้เราได้สร้างไฟล์ resources/views/app.blade.php เพื่อเป็นโครงสร้างหลักหน้าเว็บ

<html>
<body>
    @yield('content')
</body>
</html>

เราสามารถแก้ไขไฟล์ create.blade.php เพื่อเรียกใช้ไฟล์โครงสร้างหลักหน้าเว็บ

@extends('app')

@section('content')
Article create form
@endsection

หลังการแก้ไข ทดลองใช้คำสั่ง curl หรือ browser ก็จะได้ผลลัพธ์แบบด้านล่าง

$ curl http://blog.test/articles/create
<html>
<body>
    Article create form
</body>
</html>

แก้ไขไฟล์ resources/views/articles/create.blade.php โดยสร้างเว็บฟอร์ม <form> รองรับการกรอกข้อมูล title และ body และเมื่อกดปุ่ม submit ให้ฟอร์มส่งข้อมูลแบบ POST ไปที่ /articles

@extends('app')

@section('content')
<strong>Article create form</strong>
<form method="POST" action="/articles">
    <label>Title:</title><br>
    <input type="text" name="title"><br>
    <br>
    <label>Body:</title><br>
    <textarea name="body"></textarea><br>
    <br>
    <button type="submit">submit</button>
</form>
@endsection
@endsection

เปิดหน้าเว็บฟอร์ม http://blog.test/articles/create ด้วย browsesr แล้วทดลองกรอกข้อมูลในช่อง title และ body แล้วกดปุ่ม submit

create form

หลังจากกดปุ่ม submit จะขึ้น error 404 | Not Found

404 not found

สาเหตุเป็นเพราะเรายังไม่ได้กำหนด url เพื่อรองรับการ submit form

วิธีการแก้ไขทำได้โดยกำหนด url เพิ่มเติมในไฟล์ routes/web.php เพื่อรองรับการเรียกใช้ articles แบบเมธอด POST โดยจะส่งไปประมวลผลที่คลาส ArticleController ในเมธอด store

// routes/web.php
...
Route::get('articles/create', 'ArticleController@create');
Route::post('articles', 'ArticleController@store');

เพิ่มเมธอด store() ในคลาส ArticleController เพื่อรอรับข้อมูลจากการ submit form

// app/Http/Controllers/ArticleController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ArticleController extends Controller
{
    public function create()
    {
        return view('articles.create');
    }

    public function store(Request $request)
    {
        return 'store the form data.';
    }
}

สังเกตว่า เราระบุพารามิเตอร์ในเมธอด store() เพื่อเก็บค่าที่ได้รับจากการ submit form ไว้ในตัวแปรออปเจ็คชื่อ $request

เพื่อความง่าย เริ่มต้นขอกำหนดให้เมธอดนี้ส่งผลลัพธ์ง่ายๆ เป็นประโยคว่า store the form data. (ยังไม่มีการบันทึกลงฐานข้อมูล)

กลับไปที่ browser กรอกข้อมูลในหน้า http://blog.test/articles/create แล้วกด submit อีกที

หลัง submit หน้าเว็บจะขึ้น error ข้อความ 419 | Page Expired

419 page expired

ซึ่ง error นี้เป็นระบบความปลอดภัย คือฟอร์มที่จะส่งข้อมูลได้ ต้องระบุ CSRF Token ให้ถูกต้อง

วิธีการแก้ไข ต้องไปแก้ไขไฟล์ resources/views/articles/create.blade.php ระบุ @csrf ภายใต้ <form> ตัวอย่างเช่น

@extends('app')

@section('content')
<strong>Article create form</strong>
<form method="POST" action="/articles">
    @csrf
    <label>Title:</title><br>
    <input type="text" name="title"><br>
    <br>
    <label>Body:</title><br>
    <textarea name="body"></textarea><br>
    <br>
    <button type="submit">submit</button>
</form>
@endsection

หลังการเพิ่ม @csrf กลับไปที่ browser ลองเปิดหน้า http://blog.test/articles/create แล้วลองคลิกขวาที่หน้าเว็บ เพื่อ View Page Source จะเห็น <input> ชื่อ token ถูกเพิ่มขึ้นมาภายใต้ <form>

csrf token

ทดลองกรอกข้อมูล title และ body ในเว็บฟอร์ม แล้วกดปุ่ม submit อีกที

submit form

หลังจาก submit หน้าจอจะแสดงข้อความที่ได้จากเมธอด store()

show store the form data

ขั้นต่อไป เราจะแก้ไขไฟล์คลาส ArticleController ในเมธอด store() โดยจะเรียกใช้เมธอด all() ของตัวแปรออปเจ็ค $request เพื่อแสดงข้อมูลที่ได้รับจากการ submit form

dd() เป็นฟังก์ชันของ Laravel โดยเมื่อเรียกใช้ฟังก์ชันนี้ โปรแกรมจะแสดงค่าในตัวแปรบนหน้าเว็บในรูปแบบที่อ่านง่าย (dump) แล้วโปรแกรมจะหยุดทำงาน die()

// app/Http/Controllers/ArticleController.php
...
    public function store(Request $request)
    {
        dd($request->all());
    }

กลับมาที่ browser ถ้าหน้าเว็บค้างอยู่ที่หน้า store the form data ให้กดปุ่ม reload หรือ refresh ซึ่งจะทำให้ browser ส่งข้อมูล (submit) ที่เคยกรอกอีกที

ตัวอย่างการแสดงค่าออกหน้าเว็บด้วยฟังก์ชัน dd() ของการเรียกใช้ $request->all()

dd request

จะเห็นว่าเราสามารถเรียกใช้ค่าในตัวแปร ที่กำหนดในเว็บฟอร์ม ผ่านทาง $request->all()

เพื่อความเข้าใจง่าย เราจะเก็บค่านี้ไว้ในตัวแปร $input และเราจะเรียกใช้คลาสเมธอด Article::create() เพื่อบันทึกค่า title และ body ลงฐานข้อมูล

ตัวอย่างการแก้ไขเมธอด store() ในไฟล์ ArticleController โดยจะส่งค่า return ที่ได้จากการเรียกคลาสเมธอด Article::create()

หมายเหตุ อย่าลืมระบุ use App\Article; ไว้ด้านบนคลาส เนื่องจากคลาส Model และคลาส Controller อยู่คนละ namespace กัน

// app/Http/Controllers/ArticleController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Article;

class ArticleController extends Controller
{
    public function create()
    {
        return view('articles.create');
    }

    public function store(Request $request)
    {
        $input = $request->all();

        return Article::create([
            'title' => $input['title'],
            'body' => $input['body'],
        ]);
    }
}

กลับไปที่ browser แล้วลองกด refresh อีกที หน้าเว็บจะแสดงข้อมูล article ที่เพิ่มสำเร็จ

article created

ถ้าทดลองใช้ mysql เพื่อดู articles ในฐานข้อมูล ก็จะเห็นข้อมูลที่เรากรอกผ่านหน้าเว็บ

root@blog> SELECT * FROM articles;
+----+-----------------------+----------------------------+---------------------+---------------------+
| id | title                 | body                       | created_at          | updated_at          |
+----+-----------------------+----------------------------+---------------------+---------------------+
|  1 | The First article     | Body of the first article. | 2020-04-11 13:01:53 | 2020-04-11 13:01:53 |
|  3 | Updated third article | The body also updated      | 2020-04-11 13:07:35 | 2020-04-12 16:08:46 |
|  4 | test title form       | test body form             | 2020-04-25 12:55:52 | 2020-04-25 12:55:52 |
+----+-----------------------+----------------------------+---------------------+---------------------+
3 rows in set (0.00 sec)

ในตอนต่อไป ลองมาดูวิธีการอ่านข้อมูล articles เพื่อแสดงผลผ่านหน้าเว็บกัน

ข้อมูลเพิ่มเติม