【Laravel】初めてのフォーム作成

- Bladeでの送信フォーム作成時の備忘録。

# フォームの導入
- Laravelでは、LaravelCollective をインストールしないと、フォームを作成できない。

```php:インストール
% composer require laravelcollective/html
```

# Bladeでのフォーム作成
- エスケープしたい時は、**`{{  }}`**、 エスケープしたくない時は、`{!!  !!}` で記述する。

## ■ フォームの開始
- デフォルトでは、method： POST。**HTMLがサポートしてる隠しフィールドは、POSTとGETだけ**。
- PUTやDELETEは、`_method`の追加が必要（例えば、編集フォーム、削除ボタンなど）。
- 参）postで送信したものは、`$_POST['name属性名']`に格納される（配列でも同様）。
  - `$_GET`：postで送信したもの。URLの ? 以降も含む情報。
  - `$_COOKIE`：ブラウザから送信されたクッキー情報。
  - `$_REQUEST`：＄_GET、＄_POST、＄_COOKIE の全て。
  - `$_SESSION`：サーバー側に保存される変数。

### - 新規投稿フォーム

```php:フォーム入力データの送信先の指定方法のイロイロ
{{ Form::open([ データ送り先の指定 や action, ファイル使用の有無]) }}
{{ Form::open(['url' => '/']) }}                                 // URLパスでの指定
{{ Form::open(['url'=>'foo/bar', 'files'=>true]) }}              // ファイルのアップロードの場合（filesオプション）
{{ Form::open(['route' => 'route.name']) }}                      // 定義したルーティングでの指定
{{ Form::open(['route' => ['route.name', $user->id]]) }}         // パラメーター（/{●●}の部分）も一緒に渡す
{{ Form::open(['action' => 'Controller@method']) }}              // コントローラーアクションでの指定
{{ Form::open(['action' => ['Controller@method', $user->id]]) }} // パラメーターも一緒に渡す
{{ Form::open(['route' => ['user.update', 'user' => $user->id], 'method' => 'put']) }}

// POST以外のメソッドを指定する場合
{{ Form::open(['method'=>'put', 'url'=>'/']) }}
{{ Form::open(['method'=>'delete', 'route' => ['article.destroy', $article->id] ]) }}
        :
{{ Form::close() }}
```
### - デフォルトでテーブルからデータを表示したい場合
- 編集フォームなど、既に入ってる値を取得して、フォームに表示させたい場合。
- 注） Form::model では、**初期値をnullにする**必要がある!!
  - null 部分に、取得した値を入れてくれるから。

```php:編集フォーム
{{ Form::model($user, ['route'=>['user.update', $user->id]]) }}   // POSTメソッドの場合
{{ Form::model(['method'=>'put', 'url'=>'foo/bar']) }}            // PUTメソッド（編集フォームなど）
{{ Form::model(['method'=>'delete', 'url'=>'foo/bar']) }}         // DELETEメソッド（データ削除ボタンなど）
// 例
{{ Form::model($article, ['method'=>'put', 'route'=>['article.update', $article->id], 'class'=>'form-article' ]) }}
  {{ Form::text('name', null, ['placeholder'=>'名前を入力']) }}
  {{ Form::select('category_id', $categories) }}
  {{ Form::select('type', ['タイプ1'=>'名前1', 'タイプ2'=>'名前2'], null, ['data-rel'=>'chosen']) }}
  // 異なるテーブルから既存データを取得表示したい場合
  {{ Form::label('brand[name]', 'Brand (name1)', array('class' => 'brand')) }}
  {{ Form::text('brand[name1]') }}
        :
{{ Form::close() }}
```

## ■ CSRF対策
- Laravelはクロスサイトリクエストフォージェリから保護する方法がある。
  - Form::openで、**POST、PUT、DELETEメソッドでは、自動でCSRFトークンが追加されてる**。
  - 隠しCSRFフィールドを自分で追加したい時は、tokenメソッド。

```php:自分でCSRFトークンを追加する方法
// Bladeのフォームに設置する場合
  {{ Form::token() }}
//ルートにCSRFフィルターを設置する場合
  Route::post('profile', ['before'=>'csrf', function(){
       :
  }]);
```

## ■ ラベル
- ラベル名と同じ名前のフォーム要素は、自動で、ラベル名と同じidを取得する。

```php:
{{ Form::label('関連付けるカラム名', '表示する文字', ['class'=>'クラス名', ..]) }}
{{ Form::label('name', 'なまえ', ['class'=>'post_name']) }}
```


## ■ text、textarea、hidden

```php:text、textarea、hidden用フォーム
{{ Form::text('カラム名', 'デフォルト値', ['class'=>'クラス名', 'placeholder'=>'プレースホルダー', ..]) }}
{{ Form::text('titel', 'タイトル') }}
{{ Form::text('name', old('name', $user->name), ['class' => 'form-control']) }}
{{ Form:: textarea('content', null, ['placeholder' => '入力してください', 'rows' => '5']) }}
{!! Form::textarea('memo', old('memo', $user->memo), ['class' => 'form-control']) !!}

{{ Form::hidden('test', 1) }}          // name='test'、 type='hidden'、 value='1'
{{ Form::hidden('test[]', $tests) }}   // 配列を渡したい時
```

## ■ パスワード
- セキュリティ的に、value属性は設定できない仕様。初期値設定は不可。

```php:パスワード用フォーム
{{ Form::password('カラム名', ['class'=>'クラス名', ..]) }}
{{ Form::password('password', ['class'=>'awesome']) }}
```
## ■ メールアドレス

```php:メールアドレス用フォーム
{{ Form::email('カラム名', 値, 属性など) }}
{{ Form::email('owner_email', 'xxxxx@gmail.com', ['class'=>'field']) }}
```

## ■ ファイル
- フォーム開始時に、「 'files' => true 」にしとく必要がある。
- セキュリティ的に、value属性は設定できない仕様。初期値設定は不可。

```php:ファイル投稿フォーム
{{ Form::file('カラム名', ['class'=>'クラス名', ..]) }}
{{ Form::file('image') }}
{{ Form::file($name, $attributes = []) }}
```

## ■ チェックボックス、 ラジオボタン

```php:チェックボックス、ラジオボタン
{{ Form::checkbox('カラム名', '送信する値', デフォルト値の指定(checked), ['class'=>'クラス名', ..]) }} 
{{ Form::checkbox('name', 'value') }}
{{ Form::checkbox('name', 'value', true) }}  // デフォルトを選択済みにする
// 使用例
@foreach($array as $key => $val)
  {{ Form::checkbox('sample_check[]', $key, in_array($key, old('sample_check', $user->sample_check)), ['id' => 'check'.$key]) }}
  {{ Form::label('check'.$key, $val) }}
@endforeach

{{ Form::radio('name', 'value') }}
{{ Form::radio('name', 'value', true) }}     // デフォルトを選択済みにする
// 使用例
{{ Form::radio('score', $i, $i == old('score', $review->score)) }}
{{ Form::radio('gender', 'male', (old('gender')== 'male' ? true : ($user->gender == 'male')) ? true : false, ['class' => 'radio-button']) }}
@foreach($array as $key => $val)
  {{ Form::radio('sample_radio', $key, ($key == old('sample_radio', $user->sample_radio)), ['id' => 'radio'.$key]) }}
  {{ Form::label('radio'.$key, $val) }}
@endforeach
```

## ■ ドロップダウン

```php:ドロップダウン
{{ Form::select('カラム名', 配列(キー/値), 'デフォルト値(キー名)', ['placeholder' => 'null']) }}
{{ Form::select('size', ['L'=>'Large', 'S'=>'Small']) }}        // デフォルト値、placeholderの指定ない時は、配列の最初の要素が表示される
{{ Form::select('category_id', $categories) }}                  // コントローラーなどで、配列を定義してる場合　 
{{ Form::select('size', ['L'=>'Large', 'S'=>'Small'], 'S') }}   // デフォルト値を選択済みにする
{{ Form::select('size', ['L'=>'Large', 'S'=>'Small'], null, ['placeholder'=>'選択してください']) }}  // 空のプレースホルダー（optionタグに、空の要素が作成される）

// グループ分けしたリスト
{{ Form::select('animal', [
  'Cats'=>['leopard'=>'Leopard'], 
  'Dogs'=>['spaniel'=>'Spaniel'] ])
}}

// 範囲を指定して、ドロップダウンリストを作成
{{Form::selectRange('カラム名', 範囲(数値orアルファベット), デフォルト値(selected), ['class'=>'クラス名', ..])}}
{{ Form::selectRange('number', 10, 20, null, ['class'=>'size']) }}

// 月名を指定して、ドロップダウンリストを生成
{{ Form::selectMonth('カラム名', デフォルト値(数値), ['class'=>'クラス名', ..]) }}
{{ Form::selectMonth('month') }}    

{{ Form::select('sample_id', $array , old('sample_id', $user->sample_id) , ['class' => 'form-control']) }}         
```

## ■ 数値入力フォーム

```php:数値入力フォーム
{{ Form::number('カラム名', 送る値, ['class'=>'クラス名']) }}
{{ Form::number('age', 25) }}
```


## ■ 日付

```php:日付入力フォーム
{{ Form::date('カラム名', 送る値, ['class'=>'クラス名', ..]) }}
{{ Form::date('day', \Carbon\Carbon::now()) }}  // 今日を指定する場合
```


## ■ URL
- HTMLリンクの生成。

```php:URLの生成
// URLへのHTMLリンクの生成 （link_to）
echo link_to('foo/bar', $title = null, $attributes = [], $secure = null);

// アセットへのHTMLリンク生成 （link_to_asset）
echo link_to_asset('foo/bar.zip', $title = null, $attributes = [], $secure = null);

// 名前付きルートへのHTMLリンク生成 （link_to_route）
echo link_to_route('route.name', $title = null, $parameters = [], $attributes = []);

// コントローラーアクションへのHTMLリンク生成 （link_to_action）
echo link_to_action('ArticleController@getIndex', $title = null, $parameters = [], $attributes = []);
```


## ■ 送信ボタン
- buttonメソッドも同じ使い方ができる。

```php:送信ボタン
{{ Form::submit('送信ボタン', ['class'=>'クラス名', ..]) }}

{{ Form::button('登録', ['type' => 'submit', 'onfocus' => 'this.blur();']) }}
{{ Form::button('リセット', ['type' => 'reset']) }}
{{ Form::reset('リセット') }}
```












## 参） フォームマクロ
- マクロに名前とクロージャーを登録して、その名前で呼び出して使う。
- 定義方法： Form::macro 。

```php:フォームマクロの使い方
Form::macro('myField', function() {
  return '<input type="awesome">';
});

// カスタムマクロフォームの呼び出し
{{ Form::myField() }}
```

## 参） カスタムコンポーネント
- クロージャを使って、Bladeを生成するもの。
- サービスプロバイダーのbootメソッド内にコンポーネントを定義して使う。


## 参） フォームモデルアクセサー
- LaravelのEloquentAccessorを使うと、モデル属性を返す前に操作できる。
  - 例えば、日付形式を定義する場合などに便利。フォームの形式と一致しない場合は、標準アクセサー or フォームアクセサーを作成する。
- モデルでメソッドを定義して、Form::model で呼び出す流れ。

## 参） 入力値を連想配列として送信したい
- inputタグのname属性を`"配列名[キー名]"`にすれば、連想配列で送信できる（※ `"配列名['キー名']"`ではないことに注意）。


# フォームの入力欄の長さで使うBootstrap例

|class名||
|:--|:--|
|.size-xs-100<br>.size-sm-50|[xs]-[sm]-[md]-[lg]<br>5～100％で5％刻み|
|.size-xs-**|xs以上の時、**% の長さ <br>（＊＊は、5～100％の間で5％刻み）|
|.size-sm-**|sm以上の時、**% の長さ|
|.size-ｍｄ-**|md以上の時、**% の長さ|
|.size-｜ｇ-**|lg以上の時、**% の長さ|
|.size-input-name|氏名：全角15文字|
|.size-input-nameS|氏名（分割）：全角7文字|
|.size-input-company|会社名：全角16文字|
|.size-input-division|部署名：全角16文字|
|.size-input-quantity|従業員数：全角4文字|
|.size-input-zip|郵便番号：半角7文字|
|.size-input-zip3|郵便番号：半角3文字|
|.size-input-zip4|郵便番号：半角4文字|
|.size-input-pref|都道府県：全角5文字|
|.size-input-address|住所：全角25文字|
|.size-input-tel|電話番号：半角14文字|
|.size-input-telS|電話番号（分割）：半角4文字|
|.size-input-homepage|webサイト：半角60文字|
|.size-input-email|メールアドレス：半角34文字|