From 57199fe92b962c98a28ffaf4da4038fb3d90762c Mon Sep 17 00:00:00 2001 From: "kin.rinzen" Date: Thu, 5 Feb 2026 19:54:35 +0900 Subject: [PATCH] =?UTF-8?q?=E5=B8=82=E5=8C=BA=E3=83=9E=E3=82=B9=E3=82=BF?= =?UTF-8?q?=E8=A6=8F=E7=B4=84=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Http/Controllers/Admin/CityController.php | 281 ++++++++++-------- resources/views/admin/cities/_form.blade.php | 30 +- .../{create.blade.php => add.blade.php} | 6 +- resources/views/admin/cities/edit.blade.php | 11 +- .../{index.blade.php => list.blade.php} | 20 +- routes/web.php | 16 +- 6 files changed, 202 insertions(+), 162 deletions(-) rename resources/views/admin/cities/{create.blade.php => add.blade.php} (84%) rename resources/views/admin/cities/{index.blade.php => list.blade.php} (89%) diff --git a/app/Http/Controllers/Admin/CityController.php b/app/Http/Controllers/Admin/CityController.php index 4b74717..fac31ae 100644 --- a/app/Http/Controllers/Admin/CityController.php +++ b/app/Http/Controllers/Admin/CityController.php @@ -14,7 +14,7 @@ class CityController extends Controller { $sort = $request->input('sort', 'city_id'); $sortType = $request->input('sort_type', 'asc'); - $page = $request->get('page', 1); + $page = (int)$request->get('page', 1); $menuAccessService = app(\App\Services\MenuAccessService::class); @@ -31,12 +31,11 @@ class CityController extends Controller $query->where('city_name', 'like', '%' . $request->input('city_name') . '%'); } - // ソート処理 if (!empty($sort)) { $query->orderBy($sort, $sortType); } - $list = $query->paginate(20); + $list = $query->paginate(50); // インデックス超過処理 if ($list->total() > 0 && $page > $list->lastPage()) { @@ -46,8 +45,7 @@ class CityController extends Controller ]); } - return view('admin.CityMaster.list', [ - 'isMethodPost' => $request->isMethod('post'), + return view('admin.cities.list', [ 'sort' => $sort, 'sort_type' => $sortType, 'list' => $list, @@ -55,123 +53,102 @@ class CityController extends Controller ]); } + /** 新規画面 */ public function add(Request $request) { - $inputs = [ - 'city_name' => '', - 'print_layout' => '', - 'city_user' => '', - 'city_remarks' => '', - ]; + $record = new City(); - if ($request->isMethod('POST')) { - $rules = [ - 'city_name' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], - 'print_layout' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], - 'city_user' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], - 'city_remarks' => ['nullable', 'string', 'max:20'], - ]; - $messages = [ - 'city_name.required' => '市区名は必須です。', - 'city_name.regex' => '市区名は全角で入力してください。', - 'print_layout.required' => '印字レイアウトファイルは必須です。', - 'print_layout.regex' => '印字レイアウトファイルは全角で入力してください。', - 'city_user.required' => '顧客M入力不要フィールドIDは必須です。', - 'city_user.regex' => '顧客M入力不要フィールドIDは全角で入力してください。', - 'city_remarks.max' => '備考は20文字以内で入力してください。', - ]; - $validator = Validator::make($request->all(), $rules, $messages); - - $inputs = array_merge($inputs, $request->all()); - - if (!$validator->fails()) { - $maxId = DB::table('city')->max('city_id'); - $newCityId = $maxId ? $maxId + 1 : 1; - - $city = new City(); - $city->city_id = $newCityId; - $city->fill($request->only([ - 'city_name', - 'print_layout', - 'city_user', - 'city_remarks', - ])); - - if ($city->save()) { - $request->session()->flash('success', __('登録に成功しました')); - return redirect()->route('city'); - } else { - $request->session()->flash('error', __('登録に失敗しました')); - } - } else { - $inputs['errorMsg'] = $validator->errors()->all(); - } - } - - return view('admin.CityMaster.add', $inputs); - } - - public function edit(Request $request, $pk, $view = '') - { - $city = City::find($pk); - if (!$city) { - abort(404); - } - - // メニューアクセス制御確認 - $menuAccessService = app(\App\Services\MenuAccessService::class); - if (!$menuAccessService->canAccessCity($city->city_id)) { - abort(403, 'この自治体へのアクセス権限がありません。'); - } - - if ($request->isMethod('POST')) { - $rules = [ - 'city_name' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], - 'print_layout' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], - 'city_user' => ['required', 'string', 'max:10', 'regex:/^[^ -~。-゚]+$/u'], - 'city_remarks' => ['nullable', 'string', 'max:20'], - ]; - $messages = [ - 'city_name.required' => '市区名は必須です。', - 'city_name.regex' => '市区名は全角で入力してください。', - 'print_layout.required' => '印字レイアウトファイルは必須です。', - 'print_layout.regex' => '印字レイアウトファイルは全角で入力してください。', - 'city_user.required' => '顧客M入力不要フィールドIDは必須です。', - 'city_user.regex' => '顧客M入力不要フィールドIDは全角で入力してください。', - 'city_remarks.max' => '備考は20文字以内で入力してください。', - ]; - $validator = Validator::make($request->all(), $rules, $messages); - - if (!$validator->fails()) { - $city->fill($request->only([ - 'city_name', - 'print_layout', - 'city_user', - 'city_remarks', - ])); - - if ($city->save()) { - $request->session()->flash('success', __('更新に成功しました')); - return redirect()->route('city'); - } else { - $request->session()->flash('error', __('更新に失敗しました')); - } - } else { - return view('admin.CityMaster.edit', [ - 'city' => $city, - 'errorMsg' => $validator->errors()->all(), - ]); - } - } - - return view($view ?: 'admin.CityMaster.edit', [ - 'city' => $city, + return view('admin.cities.add', [ + 'record' => $record, + 'errorMsg' => [], ]); } - public function info(Request $request, $pk) + /** 登録 */ + public function store(Request $request) { - return $this->edit($request, $pk, 'CityMaster.info'); + [$rules, $messages] = $this->rulesAndMessages(); + $validator = Validator::make($request->all(), $rules, $messages); + + $record = new City(); + + if ($validator->fails()) { + + $record->fill($request->only(['city_name', 'print_layout', 'city_remarks'])); + + return view('admin.cities.add', [ + 'record' => $record, + 'errorMsg' => $validator->errors()->all(), + ]); + } + + $maxId = DB::table('city')->max('city_id'); + $newCityId = $maxId ? $maxId + 1 : 1; + + $record->city_id = $newCityId; + $record->fill($request->only([ + 'city_name', + 'print_layout', + 'city_remarks', + ])); + + if ($record->save()) { + return redirect()->route('city')->with('success', __('登録に成功しました')); + } + + return back()->withInput()->with('error', __('登録に失敗しました')); + } + + /** 編集画面 */ + public function edit(Request $request, $id) + { + $record = City::find($id); + if (!$record) { + abort(404); + } + + $this->authorizeCityAccess($record); + + return view('admin.cities.edit', [ + 'record' => $record, + 'errorMsg' => [], + ]); + } + + /** 更新 */ + public function update(Request $request, $id) + { + $record = City::find($id); + if (!$record) { + abort(404); + } + + $this->authorizeCityAccess($record); + + [$rules, $messages] = $this->rulesAndMessages(); + $validator = Validator::make($request->all(), $rules, $messages); + + if ($validator->fails()) { + // 画面に戻る時に入力を保持 + $record->fill($request->only(['city_name', 'print_layout', 'city_remarks'])); + + return view('admin.cities.edit', [ + 'record' => $record, + 'errorMsg' => $validator->errors()->all(), + ]); + } + + $record->fill($request->only([ + 'city_name', + 'print_layout', + 'city_remarks', + ])); + + if ($record->save()) { + return redirect()->route('city')->with('success', __('更新に成功しました')); + } + + return back()->withInput()->with('error', __('更新に失敗しました')); } public function delete(Request $request) @@ -180,15 +157,66 @@ class CityController extends Controller if (!$arr_pk) { return redirect()->route('city')->with('error', __('削除する市区を選択してください。')); } + if (City::destroy($arr_pk)) { return redirect()->route('city')->with('success', __("削除が完了しました。")); - } else { - return redirect()->route('city')->with('error', __('削除に失敗しました。')); + } + + return redirect()->route('city')->with('error', __('削除に失敗しました。')); + } + + private function rulesAndMessages(): array + { + $rules = [ + // 市区名:全角 / 必須 / 最大20文字 + 'city_name' => [ + 'required', + 'string', + 'max:20', + 'regex:/^[^ -~。-゚]+$/u', + ], + + // 印字レイアウトファイル:半角英数字 / 必須 / 最大255文字 + 'print_layout' => [ + 'required', + 'string', + 'max:255', + 'regex:/^[A-Za-z0-9]+$/', + ], + + // 備考:任意 / 最大255文字 + 'city_remarks' => [ + 'nullable', + 'string', + 'max:255', + ], + ]; + + $messages = [ + 'city_name.required' => '市区名は必須です。', + 'city_name.regex' => '市区名は全角文字で入力してください。', + 'city_name.max' => '市区名は20文字以内で入力してください。', + + 'print_layout.required' => '印字レイアウトファイルは必須です。', + 'print_layout.regex' => '印字レイアウトファイルは半角英数字で入力してください。', + 'print_layout.max' => '印字レイアウトファイルは255文字以内で入力してください。', + + 'city_remarks.max' => '備考は255文字以内で入力してください。', + ]; + + return [$rules, $messages]; + } + + private function authorizeCityAccess(City $city): void + { + $menuAccessService = app(\App\Services\MenuAccessService::class); + if (!$menuAccessService->canAccessCity($city->city_id)) { + abort(403, 'この自治体へのアクセス権限がありません。'); } } /** - * 自治体ダッシュボード + * 自治体ダッシュボード(そのまま残すなら、別途 route 追加が必要) */ public function dashboard(Request $request, $city_id) { @@ -197,27 +225,22 @@ class CityController extends Controller return redirect()->route('city')->with('error', '指定された自治体が見つかりません。'); } - // この自治体に関連する駐輪場データを取得 $parks = \App\Models\Park::where('city_id', $city_id)->get(); $parkIds = $parks->pluck('park_id')->toArray(); - - // この自治体の統計情報を取得 + $contractsCount = 0; $usersCount = 0; $waitingCount = 0; - + if (!empty($parkIds)) { - // 契約数を取得 $contractsCount = \App\Models\RegularContract::whereIn('park_id', $parkIds)->count(); - - // この自治体の駐輪場で契約しているユニークユーザー数を取得 + $userIds = \App\Models\RegularContract::whereIn('park_id', $parkIds) ->distinct() ->pluck('user_id') ->toArray(); $usersCount = count(array_filter($userIds)); - - // 予約待ち人数を取得(valid_flag = 1 かつ reserve_order が設定されているもの) + $waitingCount = DB::table('reserve') ->whereIn('park_id', $parkIds) ->where('valid_flag', 1) @@ -225,7 +248,7 @@ class CityController extends Controller ->where('reserve_order', '>', 0) ->count(); } - + $stats = [ 'parks_count' => $parks->count(), 'contracts_count' => $contractsCount, @@ -235,4 +258,4 @@ class CityController extends Controller return view('admin.CityMaster.dashboard', compact('city', 'parks', 'stats')); } -} \ No newline at end of file +} diff --git a/resources/views/admin/cities/_form.blade.php b/resources/views/admin/cities/_form.blade.php index 69d2518..a7f7c38 100644 --- a/resources/views/admin/cities/_form.blade.php +++ b/resources/views/admin/cities/_form.blade.php @@ -14,8 +14,8 @@ @endif -{{-- アラート(任意エラー) --}} -@if(isset($errorMsg)) +{{-- アラート(任意エラー:旧互換) --}} +@if(!empty($errorMsg)) @@ -83,9 +84,10 @@
+ maxlength="255" + value="{{ old('print_layout', $record->print_layout ?? '') }}">
@@ -95,10 +97,11 @@
- + name="city_remarks" + maxlength="255">{{ old('city_remarks', $record->city_remarks ?? '') }}
@@ -110,11 +113,11 @@ {{-- 登録/更新ボタン --}} @if(!empty($isEdit)) - @else - @endif @@ -136,5 +139,4 @@ - diff --git a/resources/views/admin/cities/create.blade.php b/resources/views/admin/cities/add.blade.php similarity index 84% rename from resources/views/admin/cities/create.blade.php rename to resources/views/admin/cities/add.blade.php index f9fcf87..84028a8 100644 --- a/resources/views/admin/cities/create.blade.php +++ b/resources/views/admin/cities/add.blade.php @@ -15,7 +15,7 @@ ホーム @@ -35,12 +35,12 @@ {{-- 新規登録フォーム --}}
@csrf @include('admin.cities._form', [ - 'isEdit' => false + 'isEdit' => false, ])
diff --git a/resources/views/admin/cities/edit.blade.php b/resources/views/admin/cities/edit.blade.php index b28b62c..b3cc808 100644 --- a/resources/views/admin/cities/edit.blade.php +++ b/resources/views/admin/cities/edit.blade.php @@ -13,7 +13,7 @@ @@ -33,24 +33,25 @@ {{-- 編集フォーム --}}
@csrf + @method('PUT') @include('admin.cities._form', [ 'isEdit' => true, - 'record' => $record + ])
{{-- 削除フォーム(非表示) --}} diff --git a/resources/views/admin/cities/index.blade.php b/resources/views/admin/cities/list.blade.php similarity index 89% rename from resources/views/admin/cities/index.blade.php rename to resources/views/admin/cities/list.blade.php index 0450563..8d23ec0 100644 --- a/resources/views/admin/cities/index.blade.php +++ b/resources/views/admin/cities/list.blade.php @@ -24,7 +24,7 @@
{{-- 並び替え用 hidden --}} -
+
@@ -33,7 +33,7 @@
@@ -74,10 +74,18 @@ {!! Session::get('error') !!}
- @elseif(isset($errorMsg)) + @elseif(!empty($errorMsg))
- {!! $errorMsg !!} + @if(is_array($errorMsg)) +
    + @foreach($errorMsg as $msg) +
  • {{ $msg }}
  • + @endforeach +
+ @else + {!! $errorMsg !!} + @endif
@endif
@@ -85,7 +93,7 @@ {{-- ▼ テーブル --}}
-
+ @csrf @@ -118,7 +126,7 @@
- 編集 diff --git a/routes/web.php b/routes/web.php index 88910fd..112b17d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -185,11 +185,17 @@ Route::middleware('auth')->group(function () { ->middleware('check.city.access'); // 市区マスタ - Route::match(['get', 'post'], '/city', [CityController::class, 'list'])->name('city'); - Route::match(['get', 'post'], '/city/add', [CityController::class, 'add'])->name('city_add'); - Route::match(['get', 'post'], '/city/edit/{id}', [CityController::class, 'edit'])->where(['id' => '[0-9]+'])->name('city_edit'); - Route::match(['get', 'post'], '/city/info/{id}', [CityController::class, 'info'])->where(['id' => '[0-9]+'])->name('city_info'); - Route::match(['get', 'post'], '/city/delete', [CityController::class, 'delete'])->name('city_delete'); + Route::get('/city', [CityController::class, 'list'])->name('city'); + Route::get('/city/add', [CityController::class, 'add'])->name('city.add'); + Route::post('/city/add', [CityController::class, 'store'])->name('city.store'); + Route::get('/city/edit/{id}', [CityController::class, 'edit']) + ->whereNumber('id') + ->name('city.edit'); + Route::put('/city/edit/{id}', [CityController::class, 'update']) + ->whereNumber('id') + ->name('city.update'); + Route::post('/city/delete', [CityController::class, 'delete'])->name('city.delete'); + //2026.02.05 kin // 駐輪場マスタ