目次
- Formファサードはとりあえず使わない
- べた書きで画面イメージを確認するサンプル
- 選択値をコントローラで受け取るサンプル
- コントローラクラスで初期値をセットするサンプル。
- Bladeテンプレート側で配列変数を処理するサンプル
- 実行イメージ
今回は、入力画面でよく使う部品である、SELECTについて整理します。
Formファサードはとりあえず使わない
Laravelには「Formファサード」があります。
これは標準インストールには含まれません。
別途インストールすれば使えます。
それを使えば、例えば、SELECTならこんな感じで書けます。
{{Form::select('size', ['L' => 'Lサイズ', 'S' => 'Sサイズ'], 'S', ['placeholder' => 'null'])}}
便利そうには見えますが、今回は使いません。
理由は「依存するのが怖い気がするから」です。
最新では標準に含まれていないけど、以前は標準に含まれていた・・というパターンの機能に依存して、後で後悔する・・パターンは、さんざん体験してきましたから。
べた書きで画面イメージを確認するサンプル
blade.phpファイルだけ編集して、画面表示から確認します。
まずはベタ書きで。
単一選択のSELECT(プルダウン)
<div class="form-group row"> <label for="sel01" class="col-md-4 col-form-label text-md-right">性別</label> <div class="col-md-6"> <select class="form-control" id="sel01" name="sel01"> <option value="1">男性</option> <option value="2" selected>女性</option> </select> </div> </div>
表示すると、こうなります。
複数選択のSELECT
<div class="form-group row"> <label for="sel02" class="col-md-4 col-form-label text-md-right">選択言語</label> <div class="col-md-6"> <select multiple class="form-control" id="sel02" name="sel02[]"> <option value="ja" selected>日本語</option> <option value="en">英語</option> <option value="de">ドイツ語</option> <option value="zh">中国語</option> </select> </div> </div>
表示するとこうなります。
単一SELECTとことなり、注意することがひとつ。
<select multiple class="form-control" id="sel02" name="sel02[]">
この部分の「name="sel02[]"」のように、multipleの場合は、nameを配列で定義しておく必要があることです。
こうしておかないと、複数選択された結果をコントローラ側で配列で受け取ることができず、一番最後に選択された値のみになってしまします。
選択値をコントローラで受け取るサンプル
nameを設定しているので、Requestクラスオブジェクトで、選択値を受け取れます。
public function store(Request $request)
{$sel01 = $request->sel01;
$sel02 = $request->sel02;}
この各変数に何がはいっているか?です。
まず、単一選択の$sel01には"1"または"2"など、選択されたoptionのvalue値です。
複数選択の$sel02は、選択されたoptionのValue値が配列ではいってきます。
なので、大抵の場合「implode」関数などを使って
$sel02ForSave = implode(',', $sel02)
のようにして「ja,de,en」のような選択されたValue値をカンマつなぎのテキストに変換してDBに保存したりします。
コントローラクラスで初期値をセットするサンプル。
DBからデータを読み込んだ・・体で、コントローラクラスから初期値をわたして表示するケースです。
Http\Controllers\DummyController.php
public function index() { $sel01Mock = "2"; $sel01Datas = [ "1" => "男性", "2" => "女性" ]; $sel01Selected = [ "1" => "", "2" => "" ]; $sel01Selected[$sel01Mock] = "selected"; $sel02Mock = preg_split("/,/", "en,zh"); print_r($sel02Mock); $sel02Datas = [ "ja" => "日本語", "en" => "英語", "de" => "ドイツ語", "zh" => "中国語" ]; $sel02Selected = [ "ja" => "", "en" => "", "de" => "", "zh" => "" ]; foreach ($sel02Mock as $key => $val) { $sel02Selected[$val] = "selected"; } return view('dummy', compact( 'sel01Datas', 'sel01Selected', 'sel02Datas', 'sel02Selected' )); }
単一SELECTと複数SELECTの両方共、コントローラでoptionの選択肢と、初期選択状態(selected)をセットしてます。
補足していきます。
単一SELECT
こちらの「DBから取得した体」は「$sel01Mock = "2";」です。
前半の例のとおり、コントローラクラスではRequestオブジェクトから、選択された「Value値」が取得できますから、DBに保存するとしたら、その値です。
つまり、"2"の女性が選択されていたものを保存して、DBから取得した想定です。
データと同じキーで「 $sel02Selected」配列を用意して、$sel01Mockの値をキーにして「selected」をセットするわけです。
複数SELECT
こちらの「DBから取得した体」は「$sel02Mock = preg_split("/,/", "en,zh");」です。
前半の例で、Multipleの場合は選択されたValue値が配列でわたってくるので、DBに保存するときには「カンマつなぎ」の文字列にして保存すると書きました。
こちらの例はその想定で、enとzhが選択されてDBに保存されていたものを読み出し、カンマで分割して、配列に戻しているわけです。
なので。
foreach ($sel02Mock as $key => $val) {
$sel02Selected[$val] = "selected";
}
こんな感じで、$sel02Selected配列を用意して、配列の値をキーにして「selected」をセットすれば良いわけです。
Bladeテンプレート側で配列変数を処理するサンプル
上記のコントローラで設定し受け渡した配列変数を処理するVIEW側です。
単一SELECT
<div class="form-group row"> <label for="sel01" class="col-md-4 col-form-label text-md-right">性別</label> <div class="col-md-6"> <select class="form-control" id="sel01" name="sel01"> @foreach($sel01Datas as $key01 => $val01) <option value="{{$key01}}" @if(empty(old())) {{ $sel01Selected[$key01] }} @elseif(old('sel01')==$key01) selected @endif >{{$val01}}</option> @endforeach </select> </div> </div>
SELECTのプルダウンリストに出力する表示項目情報は以下のループで取り出します。
@foreach($sel01Datas as $key01 => $val01)
ここで、$sel01Datasにはコントローラで
$sel01Datas = [ "1" => "男性", "2" => "女性" ];
のようにセットされているので、それを1セットずつ取り出して<option>タグを組み立てればよいわけです。
でも。
それだけでは初期表示時に明示的に「選択された状態」にすることはできません。
選択された状態にするポイントは、以下の@if~ @endifの部分です。
@if(empty(old())) {{ $sel01Selected[$key01] }}
@elseif(old('sel01')==$key01) selected
@endif
表示するケースとして
- 初期表示時にSELECTED(選択状態)にする。
- バリデーションエラーで戻った時に直前の選択状態を復元する
の2つがあります。
初期表示時は「old()」が空(empty)になりますから、それを利用して。
@if(empty(old())) {{ $sel01Selected[$key01] }}
で、コントローラでセットした「SELECTED」文字列を適用する・しないで制御することができます。
逆に、バリデーションエラーで戻った時は「old('sel01')」で直前に選択されていたValue値が取得できますから、それと一致するものに「SELECTED」をつけることで復元することができます。
マルチSELECT
マルチSELECTの場合も理屈は同じです。
ただ、SELECTEDになる項目が1つではないので、そこだけ配慮がいります。
ソースはこんな感じです。
<div class="form-group row"> <label for="sel02" class="col-md-4 col-form-label text-md-right">選択言語</label> <div class="col-md-6"> <select multiple class="form-control" id="sel02" name="sel02[]"> @foreach($sel02Datas as $key02 => $val02) <option value="{{$key02}}" @if(empty(old())) {{$sel02Selected[$key02]}} @elseif(in_array($key02,old('sel02'))) selected @endif >{{$val02}}</option> @endforeach </select> </div> </div>
表示項目のセットや、初期表示字のSELECTED(選択状態)の指定はほぼ同じです。
ただ。
@if(empty(old())) {{$sel02Selected[$key02]}}
@elseif(in_array($key02,old('sel02'))) selected
@endif
の「バリデーションエラーで戻った場合の直前の選択状態の復元」時、「 old('sel02')」で返されるのは「配列」であるという点が違います。
そのため単純に「==」などで比較はできません。
PHP関数の「in_array()」を使って、$key02の値が「 old('sel02')」で返される配列に含まれているかどうかで判断して、SELECTEDをつけています。
実行イメージ
MariaDB(MySQL)を起動し、ビルトインサーバーを動かします。
php artisan serve
それで以下のURLで動かしてみます。
初期表示は
2種類のSElECTで項目表示と初期選択はできています。
これを、「男性」「日本語」「ドイツ語」を選択に変更したうえで、コード・名前・カナを適当に入力して、バリデーションエラーを発生させます。
バリデーションエラーの直前の状態が、SELECTでも復元されてます。
OKそうですね。
このパターンを覚えておけば、SELECTはいけそうですね。
今回はこんなところで。
ではでは。