過去に
「LaravelでリレーションDBの1対多のデータに対して更新する方法(多のデータは増減有り)」
をご紹介しましたがテキストボックス(type=”text”)だけでした。
今回は更新画面でチェックボックス(checkbox)を使った主テーブルとその子(多)テーブルに対しての更新方法をご紹介します。
多のデータは増減(更新画面にて入力追加・削除)有りのデータになります。
(Laravelバージョン6系)
親子関係(1対多)の2つのテーブル構造
親子関係(1対多)の2つのテーブルを用意しました。
部署(departmentsテーブル)に所属する複数の所属社員ID(employeesテーブル)レコードが登録されてるテーブル構造です。
部署テーブル:departmentsテーブル(親)
名前 | 説明 |
---|---|
id | 主キー |
department_name | 部署名 |
所属社員テーブル:employeesテーブル(子)
名前 | 説明 |
---|---|
id | 主キー |
employee_id | 所属社員ID |
department_id | 部署ID=departmentsテーブルのid ※departmentsテーブルのテーブル名から「s」を除いた名前「department」とdepartmentsテーブルの主キー「id」にアンダーバー「_」を付けた名前「department_id」にする必要があります。こうすることでdepartmentsテーブルからidが一致したデータを取得することができます。 |
親と子のテーブルデータ用のModelを用意
※Departmentモデル、Employeeモデルを用意します。
departmentsテーブル(親)のテーブルデータ用Modelの記述
※Department.phpファイルを用意します。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Department extends Model { }
employeesテーブル(親)のテーブルデータ用Modelの記述
※Employee.phpファイルを用意します。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Employee extends Model { }
部署、所属社員ID(checkbox)の更新フォームのviewの記述
※departmentsedit.blade.phpファイルを用意します。1部署に最大5人の所属社員IDまでチェック(checkbox)できる更新フォームです。
@if (session('message')) <div class="message"> {{ session('message') }} </div> @endif @include('common.errors') <form enctype="multipart/form-data" action="{{ url('departments/update') }}" method="POST"> @csrf <div> <label for="id">部署ID</label> <div>{{$department->id}}</div> <input type="hidden" name="id" value="{{$department->id}}"> </div> <div> <label for="department_name">部署名※</label> <input type="text" id="department_name" name="department_name" value="{{ old('department_name') }}"> </div> <ul> @for($idx=0;$idx<5;$idx++) <li> <?php //登録されてる所属社員IDとcheckboxのvalue値の一致してる場合、チェック済み(checked) $employee_id = ""; $value_id = $idx+1; for($i=0;$i<count($employees);$i++){ if(isset($employees[$i]->employee_id)){ if($employees[$i]->employee_id == $value_id){ $employee_id = $employees[$i]->employee_id; break; } } } ?> <label>所属社員ID{{ $value_id }}</label> <input type="checkbox" value="{{ $value_id }}" name="employee_id[{{ $idx }}]" @if( old("employee_id.$idx", $employee_id) == $value_id) ) checked @endif> </li> @endfor </ul> <button type="submit" class="btn-entry">更新</button> </form>
Routeの記述
※ページURLは必要に応じて変更して下さい。
//更新画面 Route::post('/departmentsedit/{departments}','DepartmentsController@edit'); //更新処理 Route::post('/departments/update','DepartmentsController@update');
リレーションDBの1対多のデータに対して更新するControllerの記述
※(親)部署:departmentsテーブルデータ更新時に親テーブルのid(主キー)を使用しforeach文とsave()を使って(子)所属社員:employeesテーブルにデータを更新(update)・登録(create)処理を行います。最後に、更新画面の所属社員ID(checkbox)でチェックされた要素数よりemployeesテーブルに登録されてるレコード数が多い場合、チェックされた要素数よりオーバーしてるemployeesテーブルのレコードを削除(delete)するDepartmentsController.phpファイルを用意します。
Department、Employeeモデルの読込
namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Validation\Rule; use App\Department; //Departmentモデルを使用 use App\Employee; //Employeeモデルを使用 use Validator; //バリデーションを使用 use DB;
更新画面と更新処理(checkbox)のControllerの記述
※更新画面の表示「edit($id)~」と更新処理「update(Request $request)~」の記述です。
- 更新処理では入力後「//バリデーションチェック」を行い、「部署テーブル:departmentsテーブル(親)を更新」を行った後、「//所属社員ID(checkbox)でチェックされた要素を配列で取得」します。
- 「departmentsテーブル(親)のid(主キー)と一致する、所属社員テーブル:employeesテーブル(子)に登録されてる複数レコードを取得」します。
- foreach文内で「//更新画面の所属社員ID(checkbox)でチェックされた要素数分ループ」内で、「//employeesテーブルに登録されてるレコード数より、更新画面の所属社員ID(checkbox)でチェックされた要素より少ない場合、更新処理」「//employeesテーブルに登録されてるレコード数より、更新画面の所属社員ID(checkbox)でチェックされた要素より多い場合、登録処理」を行います。
- 最後に「//更新画面の所属社員ID(checkbox)でチェックされた要素数より、employeesテーブルに登録されてるレコード数が多い場合、チェックされた要素数よりオーバーしてるemployeesテーブルのレコードを削除(create)」します。
class DepartmentsController extends Controller{ //更新画面 public function edit($id) { $department = Department::find($id); $employees = DB::select("SELECT * FROM employees WHERE department_id = ".$id.""); return view('departmentsedit', [ 'department' => $department, 'employees' => $employees, ]); } //更新処理 public function update(Request $request) { //バリデーションチェック $validator = Validator::make($request->all(), [ 'department_name' => 'required', 'department_name' => 'max:255', ]); //バリデーション:エラー if ($validator->fails()) { return redirect('/departmentsedit') ->withInput() ->withErrors($validator); } //部署テーブル:departmentsテーブル(親)を更新 $departments = Department::find($request->id); $departments->department_name = $request->department_name; $departments->save(); //所属社員ID(checkbox)でチェックされた要素を配列で取得 $employee_ids = $request->get('employee_id'); //データ無の場合、配列変数初期化 if (!is_array($employee_ids)) { $employee_ids = array(); } //departmentsテーブル(親)のid(主キー) $department_id = $request->id; //departmentsテーブル(親)のid(主キー)と一致する、所属社員テーブル:employeesテーブル(子)に登録されてる複数レコードを取得 $employees = Employee::where('department_id', $department_id)->get(); $i = 0; //更新画面の所属社員ID(checkbox)でチェックされた要素数分ループ foreach ($employee_ids as $j => $employee_id) { //employeesテーブルに登録されてるレコード数より、更新画面の所属社員ID(checkbox)でチェックされた要素より少ない場合、更新処理 if($i < count($employees)){ $employees[$i]->employee_id = $employee_ids[$j]; $employees[$i]->save(); //employeesテーブルに登録されてるレコード数より、更新画面の所属社員ID(checkbox)でチェックされた要素より多い場合、登録処理 }else{ $employee = New Employee; $employee->department_id = $department_id; $employee->employee_id = $employee_ids[$j]; $employee->save(); } $i++; //更新画面の所属社員ID(checkbox)でチェックされた要素数より、employeesテーブルに登録されてるレコード数が多い場合、employeesテーブルのレコードを削除するためカウント }//END foreach //更新画面の所属社員ID(checkbox)でチェックされた要素数より、employeesテーブルに登録されてるレコード数が多い場合、チェックされた要素数よりオーバーしてるemployeesテーブルのレコードを削除(create) if($i < count($employees)){ for($i=$i; $i<count($employees); $i++){ Employee::where('id', $employees[$i]->id)->delete(); } } return redirect('/departmentsedit')->with('message', 'データを更新しました'); } }
※流用される場合は自己責任でお願いします。