--- tags: laravel --- # Form & HTML ![](https://i.imgur.com/1oml09M.png) ## Collective HTML套件安裝 Step 1.下載套件 `composer require laravelcollective/html:"5.8.0"` //針對5.8版本 `composer require laravelcollective/html` //針對8.x版本 Step 2.註冊provider與alias(Laravel 5.4以上非必須) 加入provider,請編輯config/app.php 在providers陣列加入以下程式碼: `Collective\Html\HtmlServiceProvider::class,` 在aliases陣列加入以下程式碼: ``` 'Form' => Collective\Html\FormFacade::class, 'Html' => Collective\Html\HtmlFacade::class ``` ## 表單Blade撰寫範例 ``` //resources/views/items/create.blade.php <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title> 新增商品 </title> </head> <body> {!! Form::open(['action'=>'ItemController@store','method'=>'POST','files'=>true]) !!} {!! Form::label('title', '標題', ['class' => 'myclass']) !!} {!! Form::text('title', null) !!}<br><br> {!! Form::label('size', '規格', ['class' => 'myclass']) !!} {!! Form::textarea('size', 'L Size', ['cols' =>50 , 'rows'=>10]) !!}<br><br> {!! Form::label('isRecommend', '是否為推薦商品', []) !!} {!! Form::checkbox('isRecommend', 1, true) !!}<br><br> {!! Form::label('colors[]', '紅色', []) !!} {!! Form::checkbox('colors[]', 'red', false) !!} {!! Form::label('colors[]', '黃色', []) !!} {!! Form::checkbox('colors[]', 'yellow', false) !!} {!! Form::label('colors[]', '綠色', []) !!} {!! Form::checkbox('colors[]', 'green', false) !!}<br><br> {!! Form::label('enabled', '是否上架', []) !!} 上架{!! Form::radio('enabled', 1, true, []) !!} 下架{!! Form::radio('enabled', 0, false, []) !!}<br><br> {!! Form::label('price', '價格', []) !!} {!! Form::number('price', 0, ['min'=>0 , 'max'=>10000]) !!}<br><br> {!! Form::label('mode:', '模式', []) !!} 經典下拉 {!! Form::select('mode', ['recommend'=>'編輯精選','season'=>'當季商品','cp'=>'超值商品'],null, ['placeholder' => '請選擇商品模式']) !!} 分群下拉 {!! Form::select('mode', ['時節'=>['summer' => '夏日熱銷','winter'=>'冬節獻禮'],'價格'=>['cp'=>'超值商品','boss'=>'老闆跳樓']],null, []) !!} 選項由後台提供 {!! Form::select('mode', $cgies,null, []) !!} {!! Form::label('month', '月份', []) !!} 月份下拉 {!! Form::selectMonth('month', null, []) !!}<br><br> {!! Form::label('number', '數字', []) !!} 區間數字下拉 {!! Form::selectRange('number', 1, 10, 5, []) !!}<br><br> {!! Form::label('pwd', '密碼', []) !!} {!! Form::password('pwd', []) !!}<br><br> {!! Form::label('email', 'Email', []) !!} {{ Form::email('email',null,[]) }}<br><br> {!! Form::label('pic', '圖片', []) !!} {!! Form::file('pic', []) !!}<br><br> {!! Form::label('date', '日期', []) !!} {!! Form::date('date',null, []) !!}<br><br> {!! Form::submit('儲存', []) !!} {!! Form::reset('重置', []) !!} {!! Form::close() !!} </body> </html> ``` ## Controller撰寫範例 ``` //app/Http/Controllers/ItemController.php public function create() { //取用表格的某兩個欄位,作為選項的來源 $cgies = \App\Models\Cgy::pluck('title','id'); return view('items.create',compact('cgies')); } public function store(Request $request) { //dd($request->all()); //驗證表單是否正確 //新增資料 $item = Item::create($request->all()); //轉址出去 return redirect('/items'); } public function edit($id) { //從cgies表格取出title和id這兩欄的資料,做成鍵值對陣列 $cgies = Cgy::pluck('title','id'); $item = Item::findOrFail($id); return view('items.edit',compact('item','cgies')); } public function update(Request $request, $id) { $item = Item::find($id); //驗證表單是否正確 //更新資料 $item = Item::updateOrCreate(['id'=>$id] ,$request->except(['_method','_token','id'])); //轉址出去 return redirect('/items'); } ``` ## 路由撰寫範例 ``` //routes/web.php Route::resource('items','ItemController'); ``` ## Form套件輸入項函式 開啟表單 `{!! Form::open(['action'=>'App\Http\Controllers\ItemController@store','method'=>'POST','files'=>true]) !!}` 內建屬性: * url 表單送出的網站路徑,ex:items * route 表單送出的路由名稱,ex:items.store * action 表單送出的控制器與方法,ex:ItemController@store * method 表單請求動詞,預設為POST * files 是否包含傳送檔案的輸入項 關閉表單 `{!! Form::close() !!}` ``` //輸入項標籤 {!! Form::label(欄位名稱, 顯示文字, 額外屬性陣列) !!} //單行文字輸入項 {!! Form::text(欄位名稱, 預設內容) !!} //多行文字輸入項 {!! Form::textarea(欄位名稱, 預設內容, 額外屬性陣列) !!} //隱藏輸入項 {!! Form::hidden(欄位名稱, 內容) !!} //額外屬性陣列範例 ['class'=>'myclass','cols'=>50,'rows'=>10] //checkbox輸入項 {!! Form::checkbox(欄位名稱, 值, 預設是否選取, 額外屬性陣列) !!} //radio輸入項 {!! Form::radio(欄位名稱, 值, 預設是否選取, 額外屬性陣列) !!} //數字輸入項 {!! Form::number(欄位名稱, 預設值, ['min'=>最小值 , 'max'=>最大值]) !!} //下拉輸入項 {!! Form::select(欄位名稱, 選項陣列,預設值, ['placeholder' => 提示文字]) !!} //密碼輸入項 {!! Form::password(欄位名稱, 額外屬性陣列) !!} //Email輸入項 {!! Form::email(欄位名稱,預設值,額外屬性陣列) !!} //檔案輸入項,記得表單頭要加入files=>true {!! Form::file(欄位名稱, 額外屬性陣列) !!} 日期輸入項 {!! Form::date(欄位名稱, 預設值, 額外屬性陣列) !!} //提交按鈕 {!! Form::submit(按鈕提示文字, []) !!} //重置按鈕 {!! Form::reset(按鈕提示文字, []) !!} ``` PS:輸入項的值如為多選,需在欄位名稱後面加上[] ## 優化表單視圖 將可重複使用的輸入項內容移到一個新的視圖 items/_form.blade.php ``` //resources/views/items/_form.blade.php {!! Form::label('title', '標題', ['class' => 'myclass']) !!} {!! Form::text('title', null) !!}<br><br> {!! Form::label('size', '規格', ['class' => 'myclass']) !!} {!! Form::textarea('size', 'L Size', ['cols' =>50 , 'rows'=>10]) !!}<br><br> {!! Form::label('enabled', '是否上架', []) !!} 上架{!! Form::radio('enabled', 1, true, []) !!} 下架{!! Form::radio('enabled', 0, false, []) !!}<br><br> {!! Form::label('price', '價格', []) !!} {!! Form::number('price', 0, ['min'=>0 , 'max'=>10000]) !!}<br><br> {!! Form::label('pic', '圖片網址', []) !!} {!! Form::text('pic','https://lorempixel.com/640/480/?13909',[]) !!}<br><br> {!! Form::label('sell_at', '銷售日期', []) !!} {!! Form::date('sell_at',\Carbon\Carbon::now(), []) !!}<br><br> {!! Form::label('cgy_id', '商品分類', []) !!} {!! Form::select('cgy_id', $cgies,null, ['placeholder' => '請選擇商品分類']) !!}<br><br> {!! Form::label('mode', '商品模式', []) !!} {!! Form::select('mode', ['recommend'=>'編輯精選','season'=>'當季商品','cp'=>'超值商品'],null, ['placeholder' => '請選擇商品模式']) !!} @if (isset($item)) {!! Form::hidden('id', $item->id) !!} @endif ``` ### 改寫create.blade.php 將新增的_form.blade.php給include進來 ``` //resources/views/items/create.blade.php 以上略 {!! Form::open(['action'=>'App\Http\Controllers\ItemController@store','method'=>'post','files'=>true]) !!} @include('items._form') {!! Form::close() !!} 以下略 ``` ### 新增edit.blade.php 改用Form::model(), 需傳入要變更的資料物件,並需指定方法為patch。同時也把新增的_form.blade.php給include進來 ``` //resources/views/items/edit.blade.php 以上略 {!! Form::model($item ,['url'=>'items/'.$item->id,'method'=>'patch','files'=>true]) !!} @include('items._form') {!! Form::close() !!} 以下略 ``` ## 如何組織 View的 Blade檔 建議針對各Model建立專屬的資料夾,再將關聯的Blade檔案存放在裡面,一般分為: * _form.blade.php 將表單結構抽取存於此檔 * create.blade.php 負責顯示建立新資源頁面 * edit.blade.php 負責顯示編輯舊資源頁面 * index.blade.php 負責顯示多筆資料頁面 * show.blade.php 負責顯示單筆資料頁面 ### _form.blade.php 編寫重點 如果表單預定採用非GET的請求方式,記得要加入CSRF Token,否則會發生錯誤,如下示範: `<input type="hidden" name="_token" value="{{ csrf_token() }}">` 此檔案將被create和edit這兩支Blade給include,可直接得到它們的變數,不需要傳入。 ### create.blade.php 編寫重點 表單內容搬移到_form.blade.php,以便於維護 Form主要的內容如下例: ``` {{ Form::open(['action'=>'App\Http\Controllers\CgyController@store','role'=>'form']) }} //action設定對應的方法 @include('cgies._form',['submitBtnText'=>'建立']) //如果要傳參數到include視圖,可用第二參數作為陣列傳入 {{ Form::close() }} ``` ### edit.blade.php 編寫重點 表單內容搬移到_form.blade.php,以便於維護 Form主要的內容如下例: ``` //為將資料直接帶入對應輸入項,改用model(),第一參數為資料model的物件,變更資料的預設方法為patch或put,因此要加上method屬性 {{ Form::model($cgy,['method'=>'patch','url'=>'backend/cgy'.$cgy->id,'role'=>'form']) }} //action設定對應的方法 @include('cgies._form',['submitBtnText'=>'修改']) //如果要傳參數到include視圖,可用第二參數作為陣列傳入 {{ Form::close() }} ``` ### 該如何讓超連結的GET請求能觸發 POST或DELETE等其他動詞 概念是為其建立一個form表單,然後透過JS來取消超連結的預設行為,並改為送出表單,如下例: ``` //此為刪除超連結,不須放在表單內,要換掉元素的ID <a onclick="event.preventDefault();document.getElementById('del-form').submit();">刪除分類</a> //指定刪除某資料的表單 {!! Form::open(['url' =>'cgies/' . $cgy->id , 'method' => 'DELETE', 'style'=>'display:none;' , 'id' => 'del-form']) !!} {!! Form::close() !!} ``` ### 上傳圖片檔案範例 ``` \\app\Http\Controllers\ProductController.php public function store(){ //$data = $request->all(); //取得所有前台傳入的資料 $data = $request->except('_token'); //取得所有前台傳入的資料 $data['options'] = implode(',',$data['options']); if ($request->hasFile('pic')) { $file = $request->file('pic'); //獲取UploadFile例項 if ( $file->isValid()) { //判斷檔案是否有效 //$filename = $file->getClientOriginalName(); //檔案原名稱 $extension = $file->getClientOriginalExtension(); //副檔名 $filename = time() . "." . $extension; //重新命名 $data['pic'] = $filename; $path = $file->storeAs('public/storage/pic',$fileName); //儲存至指定目錄 } } Product::create($data); } ```