Laravel

【更新画面checkbox編】LaravelでリレーションDBの1対多のデータに対して更新する方法

過去に
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', 'データを更新しました');
    }

}

 
 
※流用される場合は自己責任でお願いします。