input('sort', 'que_id'); $sort_type = $request->input('sort_type', 'asc'); $que_status = $request->input('que_status'); // 許可されたカラム名のリスト(DB定義に合わせて) $allowedSorts = ['que_id', 'ope_id', 'que_status', 'created_at', 'updated_at', 'user_id', 'park_id', 'que_class']; if (!in_array($sort, $allowedSorts)) { $sort = 'que_id'; } if (!in_array($sort_type, ['asc', 'desc'])) { $sort_type = 'desc'; } $query = OperatorQue::query(); // フィルタリング(絞り込み) if (!empty($que_status)) { $query->where('que_status', $que_status); } $list = $query->orderBy($sort, $sort_type) ->paginate(\App\Utils::item_per_page ?? 20); // view に $que_status を渡す return view('admin.operator_ques.list', compact('list', 'sort', 'sort_type', 'que_status')); } /** * 新規登録(画面/処理) */ public function add(Request $request) { if ($request->isMethod('get')) { // 新規時は空のレコードを用意してフォーム描画 return view('admin.operator_ques.add', array_merge( $this->formPayload(), [ 'isEdit' => false, 'record' => new OperatorQue(), // ← ★ _form.blade.php で使う用 'que_id' => null, ] )); } // POST時:バリデーション $data = $this->validateRequest($request); // 登録処理 OperatorQue::create($data); return redirect()->route('operator_ques')->with('success', '登録しました。'); } /** * 編集(画面/処理) */ public function edit($id, Request $request) { $que = OperatorQue::findOrFail($id); if ($request->isMethod('get')) { return view('admin.operator_ques.edit', array_merge( $this->formPayload($que), [ 'que_id' => $que->que_id, 'record' => $que, ] )); } $data = $this->validateRequest($request, $que->que_id); $que->fill($data)->save(); return redirect()->route('operator_ques')->with('success', '更新しました。'); } /** * 詳細(参照) */ public function info($id) { $que = OperatorQue::findOrFail($id); return view('admin.operator_ques.info', array_merge( $this->formPayload($que), ['que_id' => $que->que_id] )); } /** * 削除(複数可) */ public function delete(Request $request) { $ids = []; if ($request->filled('id')) { $ids[] = (int) $request->input('id'); } if (is_array($request->input('pk'))) { $ids = array_merge($ids, $request->input('pk')); } $ids = array_values(array_unique(array_map('intval', $ids))); if (!$ids) { return back()->with('error', '削除対象が選択されていません。'); } OperatorQue::whereIn('que_id', $ids)->delete(); return redirect()->route('operator_ques')->with('success', '削除しました。'); } /** * CSV インポート */ public function import(Request $request) { $validator = Validator::make($request->all(), [ 'file' => 'required|file|mimes:csv,txt|max:20480', ]); if ($validator->fails()) { return back()->withErrors($validator)->withInput(); } $file = $request->file('file')->getRealPath(); if (!$handle = fopen($file, 'r')) { return back()->with('error', 'CSVを読み取れません。'); } $header = fgetcsv($handle) ?: []; $header = array_map(fn($h) => trim(ltrim($h ?? '', "\xEF\xBB\xBF")), $header); $fillable = (new OperatorQue())->getFillable(); $rows = []; while (($row = fgetcsv($handle)) !== false) { $assoc = []; foreach ($header as $i => $key) { if (in_array($key, $fillable, true)) { $assoc[$key] = $row[$i] ?? null; } } if ($assoc) { $rows[] = $assoc; } } fclose($handle); DB::transaction(function () use ($rows) { foreach ($rows as $data) { OperatorQue::create($data); } }); return redirect()->route('operator_ques')->with('success', count($rows) . '件をインポートしました。'); } /** * CSV エクスポート */ public function export(): StreamedResponse { $filename = 'operator_que_' . now()->format('Ymd_His') . '.csv'; $fillable = (new OperatorQue())->getFillable(); // 見出しは fillable を流用 $response = new StreamedResponse(function () use ($fillable) { $out = fopen('php://output', 'w'); // UTF-8 BOM fprintf($out, chr(0xEF) . chr(0xBB) . chr(0xBF)); fputcsv($out, $fillable); OperatorQue::orderBy('que_id')->chunk(500, function ($chunk) use ($out, $fillable) { foreach ($chunk as $row) { $line = []; foreach ($fillable as $f) { $line[] = $row->$f ?? ''; } fputcsv($out, $line); } }); fclose($out); }); $response->headers->set('Content-Type', 'text/csv; charset=UTF-8'); $response->headers->set('Content-Disposition', "attachment; filename={$filename}"); return $response; } /** * フォームに渡す値/候補 */ private function formPayload(?OperatorQue $que = null): array { // 値 $payload = [ 'que_id' => $que->que_id ?? '', 'user_id' => $que->user_id ?? '', 'contract_id' => $que->contract_id ?? '', 'park_id' => $que->park_id ?? '', 'que_class' => $que->que_class ?? '', 'que_comment' => $que->que_comment ?? '', 'que_status' => $que->que_status ?? '', 'que_status_comment' => $que->que_status_comment?? '', 'work_instructions' => $que->work_instructions ?? '', ]; // 候補 $payload['users'] = $this->fetchUsers(); $payload['parks'] = $this->fetchParks(); return $payload; } /** * バリデーション * ※ 実テーブルの型に合わせて必要に応じて調整 */ private function validateRequest(Request $request, $queId = null): array { $rules = [ 'user_id' => 'nullable|integer', 'contract_id' => 'nullable|integer', 'park_id' => 'nullable|integer', 'que_class' => 'required|integer', 'que_comment' => 'nullable|string|max:2000', 'que_status' => 'required|integer', 'que_status_comment' => 'nullable|string|max:2000', 'work_instructions' => 'nullable|string|max:2000', // 'operator_id' => 'nullable|integer', // ログインユーザIDを使うなら不要 ]; return $request->validate($rules); } /** * 利用者候補(user_seq, user_name, user_mobile, user_homephone) * Blade 側では $users をそのまま @foreach */ private function fetchUsers() { try { return User::select('user_seq', 'user_name', 'user_mobile', 'user_homephone') ->orderBy('user_name') ->get(); } catch (\Throwable $e) { return DB::table('users') ->select(['user_seq', 'user_name', 'user_mobile', 'user_homephone']) ->orderBy('user_name') ->get(); } } /** * 駐輪場候補(park_id => park_name) */ private function fetchParks() { try { return Park::orderBy('park_name')->pluck('park_name', 'park_id'); } catch (\Throwable $e) { return DB::table('parks')->orderBy('park_name')->pluck('park_name', 'park_id'); } } }