laravel5.5の新規追加・編集画面で、可変の項目(キーワード・タグ、ホワイトリストのIP制限)の実装方法
調べてみたけど、コピペできるようなHPは見つからなかったので自分で実装してみた。
今回は、会社アカウントに紐づくホワイトリストのIP制限を実装。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(function() { // 追加ボタンを押されたら、新しい入力欄と削除ボタンを追加 $(document).on('click', '#input_add_button', function() { $(".add_to").last().append( '<div><input type="text" class="inputs" name="inputs[]"><button class="input_delete_button">削除</button></div>'); }); // 削除ボタンを押されたら、自身の親要素(削除ボタンと入力欄)を削除 $(document).on('click', '.input_delete_button', function() { if(confirm('本当に削除しますか?')){ $(this).parent().remove(); } }); }); </script> <button id="input_add_button">追加</button> <div class="add_to"> <input type="text" class="inputs" name="inputs[]"> </div> |
2, 3個までとか10個までみたいな固定値ならカラム追加でいいけど、N個までならリレーションを貼った追加テーブルが必要
1 2 3 4 5 6 7 8 9 10 11 |
Schema::create('company_ips', function (Blueprint $table) { $table->increments('id'); $table->integer('company_id')->unsigned()->comment('どの会社か?'); $table->string('admin_ip_address')->unique()->comment('その会社の管理画面に接続できるIPアドレス(ホワイトリスト)'); $table->softDeletes()->comment('ソフトデリートのためのdeleted_atカラム追加'); $table->timestamps(); // 文字列の外部キー参照元は主キーorユニーク。主キーの場合は、こちらのカラムが符号なしにする事!->unsigned() // 会社テーブルにある会社ID以外はNG $table->foreign('company_id')->references('id')->on('companies'); }); |
3, 編集画面。一行目目は必須+横に追加ボタン。二行目以降は削除ボタンを付与
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<div class="form-group required"> <?php $count_company_ip = 0; ?> @foreach ($company_ips as $company_ip) @if($count_company_ip == 0) <label class="col-md-4 control-label">接続できるグローバルIPアドレス</label> <div class="add_to"> <div class="col-md-5"> <input type="text" class="inputs form-control" name="admin_ip[]" value="{{ $company_ip->admin_ip_address }}"> </div> <div class="col-md-1"> <span id="input_add_button" class="btn" style="margin: 0px; padding:6px">追加</span> </div> </div> @else <label class="col-md-4 control-label"></label> <div class="add_to"> <div class="col-md-5"> <input type="text" class="inputs form-control" name="admin_ip[]" value="{{ $company_ip->admin_ip_address }}"> </div> <div class="col-md-1"> <span class="input_delete_button btn" style="margin: 0px; padding:6px; background-color:red">削除</span> </div> </div> @endif <?php $count_company_ip++; ?> @endforeach </div> |
4, バリデーション・更新処理(新規作成も同様)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
public function update(Request $request, $id) { $rule = [ // 接続できるグローバルIPアドレス、複数なので配列 'admin_ip.*' => [ // 配列でPOSTされると、admin_ip.0とかadmin_ip.1みたいに添字付で来るのでワイルドカードで書く 'required', // 必須 'ipv4', // IP形式だけ 'distinct', // 同じ配列内に重複があるとNG "unique:company_ips,admin_ip_address,$id,company_id" // 違う会社が使っているIPアドレスはNG ], ]; // 画面のIP入力欄と、その企業の登録IPを取得 $input_ips = $data['admin_ip']; $company_ips = Company_ip::where('company_id', $id)->pluck('admin_ip_address')->toArray(); // 差分があったら、登録されたIPを一度全て削除 // 企業担当者画面へ接続できるグローバルIPアドレスを更新する。 // array_diffは、第一引数の配列を基準でしか比較できないので、入れ替えて2回する $diff1 = array_diff($input_ips, $company_ips); $diff2 = array_diff($company_ips, $input_ips); if(count($diff1) ===0 && count($diff2) ===0 ) { }else{ Company_ip::where('company_id', $id)->delete(); // 更新画面のIPを新規に登録する foreach ($input_ips as $input_ip){ Company_ip::Create([ 'company_id'=>$id, 'admin_ip_address'=>$input_ip ]); } } unset($data['admin_ip']); // 次の画面で、処理内容を表示する $message = $company->name . 'を更新しました。'; \Session::flash('flash_message', $message); return redirect()->to('company'); } |
5, バリデーションエラーの日本語化
添字をメッセージに使いたかったけど、上手く行かなかったので、無理矢理10行目まで対応
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
'custom' => [ 'admin_ip.*' => ['unique' => ':attributeは、既に使用されています' ], ], 'attributes' => [ 'admin_ip.0' => '接続できるグローバルIPアドレスその1', 'admin_ip.1' => '接続できるグローバルIPアドレスその2', 'admin_ip.2' => '接続できるグローバルIPアドレスその3', 'admin_ip.3' => '接続できるグローバルIPアドレスその4', 'admin_ip.4' => '接続できるグローバルIPアドレスその5', 'admin_ip.5' => '接続できるグローバルIPアドレスその6', 'admin_ip.6' => '接続できるグローバルIPアドレスその7', 'admin_ip.7' => '接続できるグローバルIPアドレスその8', 'admin_ip.8' => '接続できるグローバルIPアドレスその9', 'admin_ip.9' => '接続できるグローバルIPアドレスその10', 'admin_ip.*' => "接続できるグローバルIPアドレス", ], |
問題点その1 バリデーションで戻った時に、jQueryで作った入力欄が消えてしまう
old(‘admin_ip’)とかで件数を取得したかったけど、上手く行かなかった。
問題点その2 バリデーションの日本語化で添字が使えない。
使えたとしても、0始まりだから+1行目って表示しないと駄目!