Form Builder ได้ถูกถอดออกจาก Core ของ Laravel Framework ตั้งแต่เวอร์ชั่น 5 เป็นต้นมา หากนักพัฒนาต้องการใช้การ Form Builder จะต้องติดตั้ง Package laravelcollective/html
เพิ่มเติมเอง บทความนี้จึงขอเสนอทางเลือกในการโค้ด Laravel Framework แบบไม่ใช้งาน Form Builder โดยการเปลี่ยนมาใช้ <form>
แทนครับ
ก่อนอื่นเรามาดูตัวอย่างโค้ดของการใช้งาน Form Builder กันก่อนครับ
Blade
{!! Form::open([ 'url' => '/registers', 'method' => 'post' ]) !!}
{!! Form::input('text', 'first_name', null, [ 'class' => 'input' ]) !!}
{!! Form::input('text', 'last_name', null, [ 'class' => 'input' ]) !!}
{!! Form::submit('Save', [ 'class' => 'button is-primary' ]) !!}
{!! Form::reset('Cancel', [ 'class' => 'button is-danger' ]) !!}
{!! Form::close() !!}
Form::open()
ใส่ csrf
Token ให้โดยอัตโนมัติForm::select()
ไม่จำเป็นต้องเขียน Loop เองForm::model()
ช่วยเพิ่มความสะดวกในการใช้ Form ร่วมกับ Eloquent
ก่อนที่จะเขียน <form>
ร่วมกับ Laravel Framework เรามาลองเขียน <form>
แบบพื้นฐานกันดูก่อน
Path
|-register.html
|-submit.html
|-submit.php...
เพิ่ม Attribute action
เพื่อกำหนดว่า Form จะถูก Submit ไปที่ไฟล์ไหน ซึ่งสามารถกำหนดเป็นไฟล์ HTML ก็ยังได้
ไฟล์ register.html
<form action="/submit.html">
<input type="text" name="first_name">
<input type="text" name="last_name">
<input type="submit" value="Save">
</form>
Start PHP Built-in Web Server ที่ Root Path ของโปรเจค
พิมพ์คำสั่งที่ Terminal
php -S localhost:8000
Browser
http://localhost:8000/register.html
ไฟล์ register.html
<h3>ได้รับข้อมูลเรียบร้อยแล้ว</h3>
การ Submit Form ด้วย Default Method (
GET
) จะส่งผลให้เกิดเป็น Query String ตามรูปตัวอย่าง ในการทำงานจริงเราจะไม่เลือกใช้GET
Method สำหรับการ Submit Form เนื่องจากไม่มีความปลอดภัย
POST
Methodไฟล์ register.html
<form action="/submit.html" method="POST">
...
</form>
การ Submit Form ด้วย
POST
Method ข้อมูลจะถูก Encode (เปลี่ยนแปลงรูปร่างหน้าตาเพื่อความสะดวกในการ Transportation) และ ถูกแนบไปกับ Request เราสามารถตรวจสอบ Request และ Response โดยใช้ ChromeDevTools
การ Submit Form ไปยังไฟล์ HTML นั้นสามารถทำได้ แต่ก็นำมาใช้ประโยชน์อะไรไม่ได้ เราจะลองเปลี่ยนเป็นการ Submit Form ไปยังไฟล์ PHP แทนครับ
ไฟล์ register.html
<form action="/submit.php" method="POST">
...
</form>
ไฟล์ submit.php
<?php
var_dump($_POST);
Result
array (size=2)
'first_name' => string 'John' (length=4)
'last_name' => string 'Doh' (length=3)
เรามาลอง Setup Laravel Project แบบง่ายๆ โดยมีไฟล์ที่จะนำมาใช้ตามบทความ ตามโครงสร้างด้านล่าง
Path
+-app
| +-Http
| | +-Controllers
| | | +-RegisterController
+-resources
| +-views
| | +-registers
| | | |-create.blade.php
| | | |-edit.blade.php
| +-routes
| | |-web.php
พิมพ์คำสั่งที่ Terminal
สร้าง Controller และ Route ในแบบ ReSTful
php artisan make:controller RegisterController --resource
ไฟล์ routes/web.php
Route::resource('registers', 'RegisterController');
ไฟล์ app/Http/RegisterController.php
class RegisterController extends Controller
{
public function index()
{
return 'Hello World';
}
}
พิมพ์คำสั่งที่ Terminal
php artisan serv
Browser
http://localhost:8000
จากโค้ดตัวอย่างในหัวข้อ HTML Form เราจะเห็นว่าสาระสำคัญในเรื่องการ Submit Form ก็คือ Attribute action
ของ <form>
ซึ่งเป็นตัวกำหนดว่า Form จะถูก Submit ไปที่ไฟล์ไหนเพื่อประมวลผล ดังนั้นเมื่อนำมาใช้กับ Laravel Framework เราก็เพียงแค่ระบุ URI ตามที่ต้องการ
ไฟล์ resources/views/registers/create.blade.php
<form action="/registers" method="POST">
<input type="text" name="first_name">
<input type="text" name="last_name">
<input type="submit" value="Save">
</form>
ไฟล์ App/Http/Controllers/RegisterController.php
class RegisterController extends Controller
{
public function create()
{
return view('registers.create');
}
public function store(Request $request)
{
return '<h3>Thanks</h3>';
}
}
Oops !!! เกิดปัญหาหลังจากทดลอง Submit Form
Laravel Framework มีระบบป้องการการถูกโจมตีในแบบ csrf
เราจึงต้องส่งค่า csrf
Token แนบไปกับการ Submit Form เพื่อให้ Request สามารถผ่านด่านอรหันต์นี้เข้าไปได้ แต่โชคดีที่ Laravel Framework มี Helper Function ไว้ให้เราเรียกใช้ โดยเราจะแก้ไขโค้ดตามตัวอย่างด้านล่าง
ไฟล์ creates/views/registers/create.blade.php
::: v-pre
<form action="/registers" method="POST">
{{ csrf_field() }}
</form>
:::
Refresh หน้าเว็บและลองแสดง Page Source
Page Source
<form action="/registers" method="POST">
<input type="hidden" name="_token" value="UeNq68NZdMAszrhDdS2QJ9zqX...">
</form>
csrf_field()
ได้สร้าง<input type="henden">
แก้ไขโค้ดเพิ่มเติมตามตัวอย่างด้านล่าง เพื่อ Retrieve ค่าจาก Form
ไฟล์ App/Http/Controllers/RegisterController.php
class RegisterController extends Controller
{
public function store(Request $request)
{
$inputs = request()->all();
// $inputs = request()->except(_token);
dd($inputs);
}
}
Refresh เว็บ, ป้อนข้อมูลใหม่ และลอง Submit Form
Result
array:3 [▼
"_token" => "UeNq68NZdMAszrhDdS2QJ9zq..."
"first_name" => "John"
"last_name" => "Doh"
]
action()
Helper Functionหากเราไม่คุ้นเคยกับการเรียกใช้ URL Path ตรงๆ เราสามารถใช้ Helper Function action()
เพื่อระบุการเข้าถึง Method ใน Controller ซึ่งง่ายกว่าในการทำความเข้าใจว่า Form จะถูก Submit ไปที่ใดกันแน่
ไฟล์ resources/views/registers/create.blade.php
::: v-pre
<form action="{{ action('RegisterController@store') }}" method="POST">
...
</form>
:::
การใช้ <form>
เพื่อสร้าง ReSTful Request บางคนมักจะเข้าใจผิดว่าเราสามารถทำได้โดยการแก้ไขค่า Attribute method
เหมือนในตัวอย่างด้านล่าง
<form action="..." method="PUT">
...
</form>
แต่ในความเป็นจริง PUT
และ DELETE
Method ไม่มีตัวตนอยู่จริงใน HTML Form แต่มีตัวตนใน XMLHttpRequest
(AJAX) ดังนั้นการจะประยุกต์ใช้งาน HTTP Method เช่น PUT
และ DELETE
จึงเป็นได้แค่ส่วนขยายของ POST
Method เท่านั้น ซึ่่งเป็นเรื่องของแต่ละ Framework ที่จะกำหนดวิธีการขึ้นมาเอง ซึ่งการกำหนด PUT
และ DELETE
Method ใน Laravel Framework จะใช้ Helper Function ชื่อ method_field()
เป็นตัวกำหนด ตามตัวอย่างโค้ดด้านล่าง
PUT
Methodไฟล์ creates/views/registers/edit.blade.php
::: v-pre
<form action="{{ action('RegisterController@update', [ 'id' => 1001 ]) }}" method="POST">
{{ csrf_field() }}
{{ method_field('PUT') }}
...
</form>
:::
RegisterController@update
นั้นจะต้องแนบ Argument ซึ่งเป็น ID ของ Record ที่จะถูกแก้ไขไปด้วย เราจึงจำเป็นจะต้องมี Argument เพิ่มเติมให้กับaction()
ด้วย
Page Source
<form action="http://localhost:8000/registers/1001" method="POST">
<input type="hidden" name="_token" value="UeNq68NZdMAszrhDdS2QJ9zqXQ1G02nav4e3sW6P">
<input type="hidden" name="_method" value="PUT">
...
</form>
method_feld()
ได้สร้าง<input type="henden">
DELETE
Methodไฟล์ creates/views/registers/edit.blade.php
::: v-pre
<form action="{{ action('RegisterController@destroy', [ 'id' => 1001 ]) }}" method="POST">
{{ csrf_field() }}
{{ method_field('DELETE') }}
...
</form>
:::
Page Source
<form action="http://localhost:8000/registers/1001" method="POST">
<input type="hidden" name="_token" value="UeNq68NZdMAszrhDdS2QJ9zqXQ1G02nav4e3sW6P">
<input type="hidden" name="_method" value="DELETE">
...
</form>