input('sort', 'user_seq'); $sortType = strtolower($request->input('sort_type', 'desc')) === 'asc' ? 'asc' : 'desc'; if (!in_array($sort, $sortable, true)) { $sort = 'user_seq'; } // ▼ 絞り込み値('' のときだけ無視。'0' は有効値として扱う) $user_id = trim((string) $request->input('user_id', '')); $member_id = trim((string) $request->input('member_id', '')); $user_tag_serial = trim((string) $request->input('user_tag_serial', '')); $user_phonetic = trim((string) $request->input('user_phonetic', '')); $phone = trim((string) $request->input('phone', '')); // 携帯/自宅の両方対象 $crime = trim((string) $request->input('crime', '')); // 防犯登録番号(暫定: qr_code) $user_categoryid = (string) $request->input('user_categoryid', ''); $tag_qr_flag = (string) $request->input('tag_qr_flag', ''); // 0=タグ / 1=QR $quit_flag = (string) $request->input('quit_flag', ''); // 0=いいえ / 1=はい $quit_from = (string) $request->input('quit_from', ''); // YYYY-MM-DD $quit_to = (string) $request->input('quit_to', ''); // YYYY-MM-DD // ▼ ベースクエリ(一覧で使う列が多いので一旦 * を許容) $query = DB::table('user')->select('user.*'); // ▼ テキスト系 if ($user_id !== '') $query->where('user.user_id', 'like', "%{$user_id}%"); if ($member_id !== '') $query->where('user.member_id', 'like', "%{$member_id}%"); if ($user_tag_serial !== '') $query->where('user.user_tag_serial', 'like', "%{$user_tag_serial}%"); if ($user_phonetic !== '') $query->where('user.user_phonetic', 'like', "%{$user_phonetic}%"); if ($phone !== '') { $query->where(function ($w) use ($phone) { $w->where('user.user_mobile', 'like', "%{$phone}%") ->orWhere('user.user_homephone', 'like', "%{$phone}%"); }); } if ($crime !== '') { // ※ dump に防犯登録番号の明確なカラムが無いため暫定的に qr_code を対象 $query->where('user.qr_code', 'like', "%{$crime}%"); } // ▼ セレクト/ラジオ('' 以外なら適用。'0' も通す) if ($user_categoryid !== '') $query->where('user.user_categoryid', $user_categoryid); if ($tag_qr_flag !== '') $query->where('user.tag_qr_flag', (int) $tag_qr_flag); if ($quit_flag !== '') $query->where('user.user_quit_flag', (int) $quit_flag); // ▼ 日付範囲(退会日) if ($quit_from !== '') $query->where('user.user_quitday', '>=', $quit_from); if ($quit_to !== '') $query->where('user.user_quitday', '<=', $quit_to); // ▼ 並び & ページング $list = $query->orderBy("user.{$sort}", $sortType)->paginate(20); // ▼ 画面に渡す(フォーム再描画用に絞り込み値も) return view('admin.users.list', [ 'list' => $list, 'sort' => $sort, 'sort_type' => $sortType, 'user_id' => $user_id, 'member_id' => $member_id, 'user_tag_serial' => $user_tag_serial, 'user_phonetic' => $user_phonetic, 'phone' => $phone, 'crime' => $crime, 'user_categoryid' => $user_categoryid, 'tag_qr_flag' => $tag_qr_flag, 'quit_flag' => $quit_flag, 'quit_from' => $quit_from, 'quit_to' => $quit_to, ]); } /** * CSV 出力(一覧と同じ絞り込みを適用) */ public function export(Request $request): StreamedResponse { $q = DB::table('user'); // ▼ テキスト系 if (($v = trim((string) $request->input('user_id', ''))) !== '') $q->where('user_id', 'like', "%{$v}%"); if (($v = trim((string) $request->input('user_tag_serial', ''))) !== '') $q->where('user_tag_serial', 'like', "%{$v}%"); if (($v = trim((string) $request->input('user_phonetic', ''))) !== '') $q->where('user_phonetic', 'like', "%{$v}%"); if (($v = trim((string) $request->input('phone', ''))) !== '') { $q->where(function ($w) use ($v) { $w->where('user_mobile', 'like', "%{$v}%") ->orWhere('user_homephone', 'like', "%{$v}%"); }); } if (($v = trim((string) $request->input('email', ''))) !== '') $q->where('user_primemail', 'like', "%{$v}%"); // ▼ セレクト/ラジオ('' だけスキップ。'0' は適用) $val = (string) $request->input('user_categoryid', ''); if ($val !== '') $q->where('user_categoryid', $val); $val = (string) $request->input('tag_qr_flag', ''); if ($val !== '') $q->where('tag_qr_flag', (int) $val); $val = (string) $request->input('quit_flag', ''); if ($val !== '') $q->where('user_quit_flag', (int) $val); // ▼ 退会日 範囲 if (($from = (string) $request->input('quit_from', '')) !== '') $q->where('user_quitday', '>=', $from); if (($to = (string) $request->input('quit_to', '')) !== '') $q->where('user_quitday', '<=', $to); // ▼ 取得・並び $q->orderBy('user_seq', 'desc'); $rows = $q->get([ 'user_id', 'tag_qr_flag', 'user_categoryid', 'user_name', 'user_phonetic', 'user_birthdate', 'user_age', 'user_mobile', 'user_homephone', 'user_primemail', 'user_idcard', 'user_idcard_chk_flag', 'user_chk_day', 'user_quit_flag', 'user_quitday', ]); $headers = [ '利用者ID', 'タグ/QRフラグ', '利用者分類ID', '利用者名', 'フリガナ', '生年月日', '年齢', '携帯電話番号', '自宅電話番号', 'メールアドレス', '本人確認書類', '本人確認チェック済', '本人確認日時', '退会フラグ', '退会日', ]; $filename = 'users_' . date('Ymd_His') . '.csv'; return response()->streamDownload(function () use ($headers, $rows) { // ▼ BOM(Excel対策) echo "\xEF\xBB\xBF"; $out = fopen('php://output', 'w'); fputcsv($out, $headers); foreach ($rows as $r) { // ▼ 表示値変換 $tagQr = ((int) $r->tag_qr_flag === 1) ? 'QR' : 'タグ'; $idChk = ((int) ($r->user_idcard_chk_flag ?? 0) === 1) ? '手動チェックOK' : '未チェック'; $quitFlg = ((int) $r->user_quit_flag === 1) ? 'はい' : 'いいえ'; $birth = $r->user_birthdate ? mb_substr($r->user_birthdate, 0, 10) : ''; $chkDay = $r->user_chk_day ? mb_substr($r->user_chk_day, 0, 10) : ''; $quitDay = $r->user_quitday ? mb_substr($r->user_quitday, 0, 10) : ''; fputcsv($out, [ $r->user_id, $tagQr, $r->user_categoryid, $r->user_name, $r->user_phonetic, $birth, $r->user_age, $r->user_mobile, $r->user_homephone, $r->user_primemail, $r->user_idcard, $idChk, $chkDay, $quitFlg, $quitDay, ]); } fclose($out); }, $filename, [ 'Content-Type' => 'text/csv; charset=UTF-8', 'Content-Disposition' => 'attachment; filename="' . $filename . '"', ]); } /** * 利用者登録(GET: 画面表示 / POST: 登録実行) * - 必須は最小限(user_id, user_name, user_gender, user_primemail) * - created_at/updated_at は DB 側に任せるかここで now() を入れてもOK */ public function add(Request $request) { if ($request->isMethod('get')) { return view('admin.users.add'); } // ▼ バリデーション(user_id は半角数字のみ) $rules = [ 'user_id' => ['required', 'regex:/^\d+$/'], // 半角数字のみ許可 'user_name' => ['required', 'string', 'max:255'], // 任意 'user_primemail' => ['nullable', 'email', 'max:255'], 'user_gender' => ['nullable', 'in:男性,女性'], 'member_id' => ['nullable', 'string', 'max:255'], 'user_mobile' => ['nullable', 'string', 'max:255'], 'user_homephone' => ['nullable', 'string', 'max:255'], 'user_birthdate' => ['nullable', 'date'], 'user_categoryid' => ['nullable', 'integer'], ]; // ▼ エラーメッセージ(日本語) $messages = [ 'user_id.required' => '利用者IDは必須です。', 'user_id.regex' => '利用者IDは半角数字のみで入力してください。', ]; // ▼ 属性名(日本語ラベル) $attributes = [ 'user_id' => '利用者ID', 'user_name' => '氏名', 'user_gender' => '性別', 'user_primemail' => '主メール', ]; $v = Validator::make($request->all(), $rules, $messages, $attributes); if ($v->fails()) { return back()->withErrors($v)->withInput(); } // 実在カラム名に合わせて挿入(不要なら削る/必要なら増やす) $data = [ 'user_id' => $request->input('user_id'), 'user_name' => $request->input('user_name'), 'user_gender' => $request->input('user_gender'), 'user_primemail' => $request->input('user_primemail'), 'member_id' => $request->input('member_id'), 'user_mobile' => $request->input('user_mobile'), 'user_homephone' => $request->input('user_homephone'), 'user_birthdate' => $request->input('user_birthdate'), 'user_categoryid' => $request->input('user_categoryid'), 'created_at' => now(), 'updated_at' => now(), ]; DB::table('user')->insert($data); return redirect()->route('users')->with('success', '利用者を登録しました。'); } }