Laravelでブログサイトを作る 13. 管理機能・子カテゴリの管理

はじめに
親カテゴリを基にして作成します。
一覧と登録更新を作成した前提で進めますので、ご留意ください。
Controller
app/Http/Controllers/ChildCategoryController.phpの内容は、まずParentCategoryController.phpをコピーします。
その後、親カテゴリには無かった、カラム「parent」について追加します。
変更箇所はコード内にコメントを入れていますが、目的は以下の2点です。
- 画面表示する際に、セレクトメニューで使用するための「全親カテゴリ」データを取得しテンプレートへ渡す
- 登録更新する情報に、関連する親カテゴリのIDを追加
<?php
namespace App\Http\Controllers;
use App\Models\ChildCategory; // ※今回追加
use App\Models\ParentCategory;
use Illuminate\Http\Request;
class ChildCategoryController extends Controller
{
/**
* @var ChildCategory
*/
protected $childCategory; // ※今回追加
/**
* @var ParentCategory
*/
protected $parentCategory;
/**
* 新しいコントローラインスタンスの生成 ※ChildCategoryを追加
*
* @param ChildCategory $childCategory
* @param ParentCategory $parentCategory
* @return void
*/
function __construct(ChildCategory $childCategory, ParentCategory $parentCategory) {
$this->childCategory = $childCategory;
$this->parentCategory = $parentCategory;
}
/**
* 一覧画面表示
*
* @return mixed
*/
public function list() {
// 子カテゴリデータの一覧 ※今回追加
$childCategoryData = $this->childCategory->withTrashed()->orderBy('id', 'asc')->get();
// 親カテゴリデータの一覧 ※説明用のコメントを削除して一行にまとめ
$parentCategoryData = $this->parentCategory->withTrashed()->orderBy('id', 'asc')->get();
return view('admin.childCategory', [
'childCategoryData' => $childCategoryData, // ※今回追加
'parentCategory' => $parentCategoryData,
]);
}
/**
* 子カテゴリ レコード総更新
*
* @param Request $request
* @return mixed
*/
public function update(Request $request) {
$flg = true; // $flgがfalseになるまでループします
for ($i = 1;$flg;$i++) {
// ...省略...
// 入力値を取得
$id = $request['id_' . $i];
$name = $request['name_' . $i];
$number = $request['number_' . $i];
$delete = $request['delete_' . $i];
$parent = $request['parent_' . $i]; // ※今回追加
// ...省略...
// idがあるなら上書き、なければ新規作成
$childCategoryData = $this->childCategory->withTrashed()->where('id', $id)->first();
if ($childCategoryData === null) {
$childCategoryData = new ChildCategory();
}
$childCategoryData->name = $name;
$childCategoryData->number = $number;
$childCategoryData->parent = $parent; // ※今回追加
$childCategoryData->save();
// ...省略...
}
return redirect()->route('admin_child');
}
テンプレート
resources/views/admin/childCategory.blade.php
コチラも、ベースとしてparentCategory.blade.phpをコピーして使います。
- テキストの「親」を「子」に変更
- formのaction属性を、parentからchildに変更
- 一覧表示でforeachに使用していた変数を$childCategoryData
- 表に親カテゴリの項目を追加
@extends('admin.app')
@section('adminTitle', '子カテゴリ管理') {{-- 親→子 --}}
@section('adminMain')
<article>
<section class="article">
<h2>子カテゴリ管理</h2> {{-- 親→子 --}}
<form action="{{ route('admin_parent_update') }}" method="post"> {{-- parent→child --}}
<table>
<tr>
<th>カテゴリ名</th>
<th>親カテゴリ</th> {{-- 追加 --}}
<th>表示順</th>
<th>削除</th>
</tr>
<tr id="model">
<td>
<input type="hidden" id="id" value="" />
<input type="text" id="name" value="" />
</td>
<td> {{-- 追加 --}}
<select id="parent">
@foreach ($parentCategory as $parentItem)
<option value="{{ $parentItem->id }}">{{ $parentItem->name }}</option>
@endforeach
</select>
</td>
<td><input type="number" id="number" value="" /></td>
<td>
<label>
<input type="checkbox" id="delete" value="on" />削除
</label>
</td>
</tr>
<?php $cnt = 1; ?>
@foreach ($childCategoryData as $item) {{-- parent→child --}}
<tr>
<td>
<input type="hidden" name="id_{{ $cnt }}" value="{{ $item->id }}" />
<input type="text" name="name_{{ $cnt }}" value="{{ $item->name }}" />
</td>
<td> {{-- 追加 --}}
<select name="parent_{{ $cnt }}">
@foreach ($parentCategory as $parentItem)
<option value="{{ $parentItem->id }}"
{{ ($item->parent === $parentItem->id) ? 'selected' : '' }}>
{{ $parentItem->name }}
</option>
@endforeach
</select>
</td>
<td>
<input type="number" name="number_{{ $cnt }}"
value="{{ $item->number }}" /></td>
<td>
<label>
<input type="checkbox" name="delete_{{ $cnt }}" value="on"
{{ ($item->deleted_at !== null) ? 'checked' : '' }} />削除
</label>
</td>
</tr>
<?php $cnt++; ?>
@endforeach
<tr>
<td>
<input type="hidden" name="id_{{ $cnt }}" value="" />
<input type="text" name="name_{{ $cnt }}" value="" />
</td>
<td> {{-- 追加 --}}
<select name="parent_{{ $cnt }}">
@foreach ($parentCategory as $parentItem)
<option value="{{ $parentItem->id }}">{{ $parentItem->name }}</option>
@endforeach
</select>
</td>
<td><input type="number" name="number_{{ $cnt }}" value="{{ $cnt }}" /></td>
<td>
<label>
<input type="checkbox" name="delete_{{ $cnt }}" value="on" />削除
</label>
</td>
</tr>
</table>
<input type="hidden" id="max" value="{{ $cnt }}" />
{{-- CSRFトークン --}}
{{ csrf_field() }}
<input type="button" value="+ 入力枠追加" id="addInput" />
<input type="submit" value="更新" />
</form>
</section>
</article>
@endsection
JavaScript
public/js/admin.js
入力枠追加の際に実行されるJavaScriptにも、親カテゴリについてを追記します。
lengthを使用して、「要素がある時」としているので、親子カテゴリの処理をできるだけ共通化しています。
$(document)
// 親カテゴリの入力枠追加
.on('click', '#addInput', function(){
// 次の番号を算出
const max = $('#max');
const nextNum = parseInt(max.val()) + 1;
max.val(nextNum);
// id=modelになっているtr要素を、idを削除した上でcloneする
const clone = $('#model').clone(true).removeAttr('id');
// cloneしたtr内の各name属性を変更し、識別用のidを削除しておく
$('#name', clone).attr('name', 'name_' + nextNum).removeAttr('id');
$('#number', clone).attr('name', 'number_' + nextNum).val(nextNum).removeAttr('id');
$('#id', clone).attr('name', 'id_' + nextNum).removeAttr('id');
$('#delete', clone).attr('name', 'delete_' + nextNum).removeAttr('id');
if ($('#parent', clone).length > 0) { // ※追加
$('#parent', clone).attr('name', 'parent_' + nextNum).removeAttr('id');
}
// テーブルに追加
clone.appendTo('table');
})
;
2022-05-06 09:00:00
