Laravel5でForm & Htmlコンポーネントを有効にする


Laravel5では、ビューで利用するForm、Htmlファサードを含むコンポーネントはコアから外され、コミュニティパッケージLaravel CollectiveからForm & Htmlとして提供されています。

Laravelフレームワークが提供するbladeテンプレートの機能だけでもそこまで困ることは無いですが、フォーム要素の中でとくに扱いが面倒なプルダウン(select要素)とチェックボックスあたりはやはり便利なので入れておいた方が良いパッケージです。

セットアップ手順

利用するための手順は以下の通りです(Laravel 5.5で確認)。

Composerでコンポーネントを追加

$ composer require "laravelcollective/html":"^5.4.0"

プロバイダとファサードの登録

v5.6以前のドキュメントには、config/app.phpprovidersaliasに設定を追加するように書いてありますが、現在は、composer.jsonextra.laravelにロードすべきプロバイダとファサードが指定してあるので、手動で追加する必要はありません。

// laravelcollective/htmlのcomposer.json
        "laravel": {
            "providers": [
                "Collective\\Html\\HtmlServiceProvider"
            ],
            "aliases": {
                "Form": "Collective\\Html\\FormFacade",
                "Html": "Collective\\Html\\HtmlFacade"
            }
        }

参照: Package Development – Laravel – The PHP Framework For Web Artisans

使い方

Bootstrapを利用したフォームの実装例で説明してみます。
Laravel 5.5 は bootstrap-sass を利用しているので、Bootstrapのバージョンは3になります。

$ php artisan make:model Customer -mc

マイグレーションには以下のようなフィールドを追加します。

// database/migrations/YYYY_MM_DD_070946_create_customers_table.php
    public function up()
    {
        Schema::create('customers', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name'); // テキスト
            $table->string('state'); // プルダウン
            $table->integer('age'); // プルダウン
            $table->boolean('has_contract'); // チェックボックス
            $table->timestamps();
        });
    }

コントローラは、フォームのテンプレート resources/views/customer/create.blade.phpを返すcreateアクションと、フォームのPOST先のアクションstoreのみを実装しておきます。
storeアクションはPOSTされたリクエストパラメータをflashしてフォームにリダイレクトするだけです。これは、テンプレートでパラメータの値をoldメソッドで取得し、セットし直す動作を確認するための最小限の実装をしています。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class CustomerController extends Controller
{
    public function create() {
        return view('customer.create');
    }

    public function store(Request $request) {
        // TODO store customer
        $request->flash();
        return redirect()->route('customer.create');
    }
}

ルーティングに以下を追加しておきます。

Route::get('/customer/create', 'CustomerController@create')->name('customer.create');
Route::post('/customer/store', 'CustomerController@store')->name('customer.store');

フォームのテンプレートは以下のようになります。

<!doctype html>
<html lang="{{ app()->getLocale() }}">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>LaravelCollective/HTML</title>
  <link rel="stylesheet" href="{{ asset('css/app.css') }}">
  <style>
    html, body {
        background-color: #fff;
        color: #636b6f;
        font-family: 'Raleway', sans-serif;
        font-weight: 100;
        height: 100vh;
        margin: 1.5rem;
    }
  </style>
</head>

<body>
  {{ Form::open(['route' => 'customer.store']) }}
    <div class="form-group">
      <label>氏名</label>
      {{Form::text('name', old('name'), ['class' => 'form-control'])}}
    </div>
    <div class="form-group">
      <label>都道府県</label>
      {{Form::select('state', ['01' => '北海道', '02' => '青森'], old('state'), ['class' => 'form-control'])}}
    </div>
    <div class="form-group">
      <label>住所</label>
      {{Form::textarea('address', old('address'), ['class' => 'form-control', 'rows' => '3'])}}
    </div>
    <div class="form-group">
      <label>年齢</label>
      {{Form::selectRange('age', 20, 100, old('age'), ['class' => 'form-control'])}}
    </div>
    <div class="form-group">
      <label>購入済み</label>
      {{Form::checkbox('has_contract', 'true', old('has_contract'))}}
    </div>
    <div>
      {{Form::submit('保存', ['class' => 'btn btn-primary'])}}
    </div>
  {{ Form::close() }}
</body>

</html>

上記コードのポイントとしては、スタイルシートcss/app.cssを読み込んでBootstrapのスタイルシートを適用していること、flashした入力データをold関数で取得して値にセットし直しているあたりです。

実行結果は以下、フォームを適当に入力して[保存]すると値が保持されていることを確認できます。(コントローラの$request->flashを削除すると保持されないことも確認できます)

,