263 lines
8.4 KiB
PHP
263 lines
8.4 KiB
PHP
<?php
|
||
namespace App\Http\Controllers\Admin;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use Illuminate\Http\Request;
|
||
use App\Models\Ope;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Validator;
|
||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||
|
||
class OpeController extends Controller
|
||
{
|
||
/**
|
||
* 一覧
|
||
*/
|
||
public function list(Request $request)
|
||
{
|
||
$inputs = [
|
||
'isMethodPost' => $request->isMethod('post'),
|
||
'sort' => $request->input('sort', 'ope_id'),
|
||
'sort_type' => $request->input('sort_type', 'asc'),
|
||
'isExport' => false,
|
||
];
|
||
|
||
// Blade 側は $list / $sort / $sort_type を参照
|
||
$list = Ope::search($inputs);
|
||
$sort = $inputs['sort'];
|
||
$sort_type = $inputs['sort_type'];
|
||
|
||
|
||
return view('admin.opes.list', compact('list', 'sort', 'sort_type'));
|
||
}
|
||
|
||
/**
|
||
* 新規登録(GET 画面 / POST 保存)
|
||
*/
|
||
public function add(Request $request)
|
||
{
|
||
if ($request->isMethod('get')) {
|
||
|
||
return view('admin.opes.add', [
|
||
|
||
'isEdit' => false,
|
||
'record' => new Ope(),
|
||
'ope_id' => null,
|
||
'ope_name' => '',
|
||
'ope_type' => '',
|
||
'ope_mail' => '',
|
||
'ope_phone'=> '',
|
||
|
||
'ope_sendalart_que1' => 0, 'ope_sendalart_que2' => 0, 'ope_sendalart_que3' => 0,
|
||
'ope_sendalart_que4' => 0, 'ope_sendalart_que5' => 0, 'ope_sendalart_que6' => 0,
|
||
'ope_sendalart_que7' => 0, 'ope_sendalart_que8' => 0, 'ope_sendalart_que9' => 0,
|
||
'ope_sendalart_que10'=> 0, 'ope_sendalart_que11'=> 0, 'ope_sendalart_que12'=> 0,
|
||
'ope_sendalart_que13'=> 0,
|
||
'ope_auth1' => '', 'ope_auth2' => '', 'ope_auth3' => '', 'ope_auth4' => '',
|
||
'ope_quit_flag' => 0, 'ope_quitday' => '',
|
||
]);
|
||
}
|
||
|
||
// 入力値を一旦取得
|
||
$data = $request->all();
|
||
|
||
// --- バリデーション ---
|
||
$rules = [
|
||
'login_id' => 'required|string|max:255|unique:ope,login_id',
|
||
'ope_name' => 'required|string|max:255',
|
||
'ope_type' => 'required|string|max:50',
|
||
'ope_mail' => [
|
||
'required',
|
||
function ($attribute, $value, $fail) {
|
||
// ; でも , でもOK、保存時は ; に統一
|
||
$emails = array_map('trim', explode(';', str_replace(',', ';', $value)));
|
||
foreach ($emails as $email) {
|
||
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||
$fail("無効なメールアドレス形式です: {$email}");
|
||
}
|
||
}
|
||
}
|
||
],
|
||
'ope_phone' => 'nullable|string|max:50',
|
||
'password' => 'required|string|min:8|confirmed',
|
||
];
|
||
|
||
$request->validate($rules);
|
||
|
||
// --- 保存用にメールを ; 区切りに統一 ---
|
||
$emails = array_filter(array_map('trim', explode(';', str_replace(',', ';', $data['ope_mail']))));
|
||
$data['ope_mail'] = implode(';', $emails);
|
||
|
||
// 保存処理
|
||
$ope = new Ope();
|
||
$ope->fill($data);
|
||
$ope->save();
|
||
|
||
return redirect()->route('opes')->with('success', '登録しました。');
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 編集(GET 画面 / POST 更新)
|
||
*/
|
||
public function edit($id, Request $request)
|
||
{
|
||
$ope = Ope::getByPk($id);
|
||
if (!$ope) abort(404);
|
||
|
||
if ($request->isMethod('get')) {
|
||
return view('admin.opes.edit', [
|
||
'isEdit' => true,
|
||
'record' => $ope,
|
||
]);
|
||
}
|
||
|
||
// 入力値を一旦取得
|
||
$data = $request->all();
|
||
|
||
// --- バリデーション ---
|
||
$rules = [
|
||
'login_id' => "required|string|max:255|unique:ope,login_id,{$id},ope_id", // 編集時は自分を除外
|
||
'ope_name' => 'required|string|max:255',
|
||
'ope_type' => 'required|string|max:50',
|
||
'ope_phone' => 'nullable|string|max:50',
|
||
'ope_mail' => [
|
||
'required',
|
||
function ($attribute, $value, $fail) {
|
||
// , でも ; でもOKにする
|
||
$emails = array_map('trim', explode(';', str_replace(',', ';', $value)));
|
||
foreach ($emails as $email) {
|
||
if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||
$fail("無効なメールアドレス形式です: {$email}");
|
||
}
|
||
}
|
||
}
|
||
],
|
||
'password' => 'nullable|string|min:8|confirmed', // 編集時は任意
|
||
];
|
||
|
||
$request->validate($rules);
|
||
|
||
// --- 保存用にメールを ; 区切りに統一 ---
|
||
if (!empty($data['ope_mail'])) {
|
||
$emails = array_filter(array_map('trim', explode(';', str_replace(',', ';', $data['ope_mail']))));
|
||
$data['ope_mail'] = implode(';', $emails);
|
||
}
|
||
|
||
// パスワード空なら更新しない
|
||
if (empty($data['password'])) {
|
||
unset($data['password']);
|
||
}
|
||
|
||
// 保存処理
|
||
$ope->fill($data);
|
||
$ope->save();
|
||
|
||
return redirect()->route('opes')->with('success', '更新しました。');
|
||
}
|
||
|
||
|
||
/**
|
||
* 削除(単体 or 複数)
|
||
*/
|
||
|
||
public function delete(Request $request)
|
||
{
|
||
$ids = [];
|
||
|
||
// 単体削除
|
||
if ($request->filled('id')) {
|
||
$ids[] = (int) $request->input('id');
|
||
}
|
||
|
||
// 複数削除
|
||
if ($request->filled('ids')) {
|
||
$ids = array_merge($ids, array_map('intval', (array)$request->input('ids')));
|
||
}
|
||
|
||
$ids = array_unique($ids);
|
||
|
||
if (!$ids) {
|
||
return back()->with('error', '削除対象が選択されていません。');
|
||
}
|
||
|
||
Ope::deleteByPk($ids);
|
||
|
||
return redirect()->route('opes')->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();
|
||
$handle = fopen($file, 'r');
|
||
if (!$handle) return back()->with('error', 'CSVを読み取れません。');
|
||
|
||
$header = fgetcsv($handle);
|
||
$header = array_map(fn($h) => trim(ltrim($h ?? '', "\xEF\xBB\xBF")), $header);
|
||
|
||
$fillable = (new Ope())->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) {
|
||
Ope::create($data);
|
||
}
|
||
});
|
||
|
||
return redirect()->route('opes')->with('success', count($rows) . '件をインポートしました。');
|
||
}
|
||
|
||
/**
|
||
* CSVエクスポート
|
||
*/
|
||
public function export(): StreamedResponse
|
||
{
|
||
$filename = 'ope_' . now()->format('Ymd_His') . '.csv';
|
||
$fillable = (new Ope())->getFillable();
|
||
|
||
$response = new StreamedResponse(function () use ($fillable) {
|
||
$out = fopen('php://output', 'w');
|
||
fprintf($out, chr(0xEF) . chr(0xBB) . chr(0xBF)); // BOM
|
||
fputcsv($out, $fillable);
|
||
|
||
Ope::orderBy('ope_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;
|
||
}
|
||
}
|