市区マスタ機能のメソッド整理し、ルーティングを更新
This commit is contained in:
parent
f850707848
commit
466dc98e17
@ -1,44 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Http\Requests\CityRequest;
|
||||
use App\Models\City;
|
||||
use App\Services\CityService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
|
||||
class CityController extends Controller
|
||||
final class CityController extends Controller
|
||||
{
|
||||
public function list(Request $request)
|
||||
public function index(Request $request, CityService $service): View|RedirectResponse
|
||||
{
|
||||
$sort = $request->input('sort', 'city_id');
|
||||
$sortType = $request->input('sort_type', 'asc');
|
||||
$page = $request->get('page', 1);
|
||||
$sort = (string) $request->input('sort', 'city_id');
|
||||
$sortType = (string) $request->input('sort_type', 'asc');
|
||||
$page = (int) $request->get('page', 1);
|
||||
|
||||
$query = City::query();
|
||||
|
||||
if ($request->filled('city_name')) {
|
||||
$query->where('city_name', 'like', '%' . $request->input('city_name') . '%');
|
||||
// ソート許可(安全 + 規約)
|
||||
$sortable = ['city_id', 'city_name', 'print_layout', 'city_remarks', 'created_at', 'updated_at'];
|
||||
if (!in_array($sort, $sortable, true)) {
|
||||
$sort = 'city_id';
|
||||
}
|
||||
|
||||
// 排序处理
|
||||
if (!empty($sort)) {
|
||||
$query->orderBy($sort, $sortType);
|
||||
$sortType = strtolower($sortType);
|
||||
if (!in_array($sortType, ['asc', 'desc'], true)) {
|
||||
$sortType = 'asc';
|
||||
}
|
||||
|
||||
$list = $query->paginate(20);
|
||||
$list = $service->paginateList(
|
||||
$request->input('city_name'),
|
||||
$sort,
|
||||
$sortType
|
||||
);
|
||||
|
||||
// 页码越界处理
|
||||
if ($list->total() > 0 && $page > $list->lastPage()) {
|
||||
return redirect()->route('city', [
|
||||
return redirect()->route('cities.index', [
|
||||
'sort' => $sort,
|
||||
'sort_type' => $sortType,
|
||||
]);
|
||||
}
|
||||
|
||||
return view('admin.CityMaster.list', [
|
||||
'isMethodPost' => $request->isMethod('post'),
|
||||
return view('admin.cities.index', [
|
||||
'sort' => $sort,
|
||||
'sort_type' => $sortType,
|
||||
'list' => $list,
|
||||
@ -46,129 +52,58 @@ class CityController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function add(Request $request)
|
||||
public function create(): View
|
||||
{
|
||||
$inputs = [
|
||||
'city_name' => '',
|
||||
'print_layout' => '',
|
||||
'city_user' => '',
|
||||
'city_remarks' => '',
|
||||
];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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.create', [
|
||||
'record' => new City(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function info(Request $request, $pk)
|
||||
public function store(CityRequest $request, CityService $service): RedirectResponse
|
||||
{
|
||||
return $this->edit($request, $pk, 'CityMaster.info');
|
||||
$service->create($request->validated());
|
||||
|
||||
return redirect()
|
||||
->route('cities.index')
|
||||
->with('success', __('登録に成功しました'));
|
||||
}
|
||||
|
||||
public function delete(Request $request)
|
||||
public function edit(int $id): View
|
||||
{
|
||||
$arr_pk = $request->get('pk');
|
||||
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', __('削除に失敗しました。'));
|
||||
}
|
||||
$city = City::findOrFail($id);
|
||||
|
||||
return view('admin.cities.edit', [
|
||||
'record' => $city,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(CityRequest $request, int $id, CityService $service): RedirectResponse
|
||||
{
|
||||
$city = City::findOrFail($id);
|
||||
|
||||
$service->update($city, $request->validated());
|
||||
|
||||
return redirect()
|
||||
->route('cities.index')
|
||||
->with('success', __('更新に成功しました'));
|
||||
}
|
||||
|
||||
public function destroy(Request $request): RedirectResponse
|
||||
{
|
||||
$ids = $request->input('pk');
|
||||
|
||||
// pk が単体でも配列でも受けられるようにする(編集画面/一覧画面両対応)
|
||||
if ($ids === null || $ids === '' || $ids === []) {
|
||||
return redirect()
|
||||
->route('cities.index')
|
||||
->with('error', __('削除する市区を選択してください。'));
|
||||
}
|
||||
$ids = is_array($ids) ? $ids : [$ids];
|
||||
|
||||
$deleted = City::destroy($ids);
|
||||
|
||||
return $deleted
|
||||
? redirect()->route('cities.index')->with('success', __('削除が完了しました。'))
|
||||
: redirect()->route('cities.index')->with('error', __('削除に失敗しました。'));
|
||||
}
|
||||
}
|
||||
|
||||
39
app/Http/Requests/CityRequest.php
Normal file
39
app/Http/Requests/CityRequest.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
final class CityRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
|
||||
return [
|
||||
'city_name' => ['required', 'string', 'max:20', 'regex:/^[^ -~。-゚]+$/u'],
|
||||
'print_layout' => ['required', 'string', 'max:255', 'regex:/^[A-Za-z0-9]+$/'],
|
||||
'city_remarks' => ['nullable', 'string', 'max:255'],
|
||||
];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'city_name.required' => '市区名は必須です。',
|
||||
'city_name.regex' => '市区名は全角文字で入力してください。',
|
||||
'city_name.max' => '市区名は20文字以内で入力してください。',
|
||||
|
||||
'print_layout.required' => '印字レイアウトファイルは必須です。',
|
||||
'print_layout.regex' => '印字レイアウトファイルは半角英数字で入力してください。',
|
||||
'print_layout.max' => '印字レイアウトファイルは255文字以内で入力してください。',
|
||||
|
||||
'city_remarks.max' => '備考は255文字以内で入力してください。',
|
||||
];
|
||||
}
|
||||
}
|
||||
50
app/Services/CityService.php
Normal file
50
app/Services/CityService.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\City;
|
||||
use App\Utils;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
|
||||
final class CityService
|
||||
{
|
||||
public function paginateList(
|
||||
?string $cityName,
|
||||
string $sort,
|
||||
string $sortType
|
||||
): LengthAwarePaginator {
|
||||
$query = City::query();
|
||||
|
||||
if ($cityName !== null && $cityName !== '') {
|
||||
$query->where('city_name', 'like', '%' . $cityName . '%');
|
||||
}
|
||||
|
||||
$query->orderBy($sort, $sortType);
|
||||
|
||||
return $query->paginate(Utils::item_per_page);
|
||||
}
|
||||
|
||||
public function create(array $validated): City
|
||||
{
|
||||
return City::create($this->payload($validated));
|
||||
}
|
||||
|
||||
public function update(City $city, array $validated): City
|
||||
{
|
||||
$city->fill($this->payload($validated));
|
||||
$city->save();
|
||||
|
||||
return $city;
|
||||
}
|
||||
|
||||
private function payload(array $validated): array
|
||||
{
|
||||
return [
|
||||
'city_name' => $validated['city_name'],
|
||||
'print_layout' => $validated['print_layout'],
|
||||
'city_remarks' => $validated['city_remarks'] ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -89,20 +89,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- {{-- ▼ 顧客M入力不要フィールドID --}}
|
||||
<div class="form-group col-3">
|
||||
<label class="form-label required">{{ __('顧客M入力不要フィールドID') }}</label>
|
||||
</div>
|
||||
<div class="form-group col-9">
|
||||
<div class="input-group">
|
||||
<input type="text"
|
||||
name="city_user"
|
||||
class="form-control form-control-lg"
|
||||
placeholder="{{ __('顧客M入力不要フィールドID') }}"
|
||||
value="{{ old('city_user', $record->city_user ?? ($city_user ?? '')) }}">
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
{{-- ▼ 備考 --}}
|
||||
<div class="form-group col-3">
|
||||
<label>{{ __('備考') }}</label>
|
||||
|
||||
@ -11,9 +11,11 @@
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<ol class="breadcrumb float-sm-right text-sm">
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">ホーム</a></li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('city') }}">市区マスタ</a>
|
||||
<a href="{{ route('home') }}">ホーム</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('cities.index') }}">市区マスタ</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">新規</li>
|
||||
</ol>
|
||||
@ -30,9 +32,10 @@
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
|
||||
{{-- 新規登録フォーム --}}
|
||||
<form id="form_add"
|
||||
method="post"
|
||||
action="{{ route('city_add') }}?back={{ urlencode(request()->get('back', request()->fullUrl())) }}"
|
||||
method="POST"
|
||||
action="{{ route('cities.store') }}?back={{ urlencode(request()->get('back', request()->fullUrl())) }}"
|
||||
enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
<ol class="breadcrumb float-sm-right text-sm">
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">ホーム</a></li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ route('city') }}">市区マスタ</a>
|
||||
<a href="{{ route('cities.index') }}">市区マスタ</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">編集</li>
|
||||
</ol>
|
||||
@ -33,9 +33,9 @@
|
||||
|
||||
{{-- 編集フォーム --}}
|
||||
<form id="form_edit"
|
||||
action="{{ route('city_edit', ['id' => $record->city_id]) }}?back={{ urlencode(request()->get('back', request()->fullUrl())) }}"
|
||||
method="POST"
|
||||
enctype="multipart/form-data">
|
||||
action="{{ route('cities.update', ['id' => $record->city_id]) }}?back={{ urlencode(request()->get('back', request()->fullUrl())) }}"
|
||||
method="POST"
|
||||
enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
@include('admin.cities._form', [
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
{{-- 削除フォーム(非表示) --}}
|
||||
<form id="form_delete"
|
||||
action="{{ route('city_delete') }}"
|
||||
action="{{ route('cities.destroy') }}"
|
||||
method="POST"
|
||||
style="display:none;">
|
||||
@csrf
|
||||
@ -59,5 +59,4 @@
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<!-- /.content -->
|
||||
@endsection
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
<div class="container-fluid">
|
||||
|
||||
{{-- 並び替え用 hidden --}}
|
||||
<form method="GET" action="{{ route('city') }}" id="list-form">
|
||||
<form method="GET" action="{{ route('cities.index') }}" id="list-form">
|
||||
<input type="hidden" name="sort" id="sort" value="{{ $sort ?? '' }}">
|
||||
<input type="hidden" name="sort_type" id="sort_type" value="{{ $sort_type ?? '' }}">
|
||||
</form>
|
||||
@ -33,7 +33,7 @@
|
||||
<div class="col-lg-12 mb-3 px-0">
|
||||
<button type="button"
|
||||
class="btn btn-sm btn-primary mr10"
|
||||
onclick="location.href='{{ route('city_add') }}?back={{ urlencode(request()->fullUrl()) }}'">
|
||||
onclick="location.href='{{ route('cities.create') }}?back={{ urlencode(request()->fullUrl()) }}'">
|
||||
新規
|
||||
</button>
|
||||
|
||||
@ -62,7 +62,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- ▼ フラッシュメッセージ(利用者分類マスタと同じ見せ方) --}}
|
||||
{{-- ▼ フラッシュメッセージ --}}
|
||||
<div class="form col-lg-12 px-0">
|
||||
@if(Session::has('success'))
|
||||
<div class="alert alert-success alert-dismissible">
|
||||
@ -85,7 +85,7 @@
|
||||
{{-- ▼ テーブル --}}
|
||||
<div class="col-lg-12 mb20 px-0">
|
||||
<div class="table-responsive">
|
||||
<form id="form_delete" method="POST" action="{{ route('city_delete') }}">
|
||||
<form id="form_delete" method="POST" action="{{ route('cities.destroy') }}">
|
||||
@csrf
|
||||
|
||||
<table class="table table-bordered dataTable text-nowrap">
|
||||
@ -118,7 +118,7 @@
|
||||
<td style="background-color:#faebd7;">
|
||||
<div class="d-flex align-items-center">
|
||||
<input type="checkbox" name="pk[]" value="{{ $city->city_id }}">
|
||||
<a href="{{ route('city_edit', ['id' => $city->city_id]) }}?back={{ urlencode(request()->fullUrl()) }}"
|
||||
<a href="{{ route('cities.edit', ['id' => $city->city_id]) }}?back={{ urlencode(request()->fullUrl()) }}"
|
||||
class="btn btn-sm btn-outline-primary ml10">
|
||||
編集
|
||||
</a>
|
||||
@ -151,12 +151,45 @@ Route::middleware('auth')->group(function () {
|
||||
// sou end
|
||||
|
||||
// ou start
|
||||
// 市区マスタ
|
||||
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::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');
|
||||
|
||||
// 市区マスタ(cities.*)
|
||||
Route::prefix('cities')->group(function () {
|
||||
|
||||
// 一覧(画面)
|
||||
Route::get('/', [\App\Http\Controllers\Admin\CityController::class, 'index'])
|
||||
->name('cities.index');
|
||||
|
||||
// 新規(画面)
|
||||
Route::get('/create', [\App\Http\Controllers\Admin\CityController::class, 'create'])
|
||||
->name('cities.create');
|
||||
|
||||
// 新規(登録)
|
||||
Route::post('/', [\App\Http\Controllers\Admin\CityController::class, 'store'])
|
||||
->name('cities.store');
|
||||
|
||||
// 編集(画面)
|
||||
Route::get('/{id}/edit', [\App\Http\Controllers\Admin\CityController::class, 'edit'])
|
||||
->whereNumber('id')
|
||||
->name('cities.edit');
|
||||
|
||||
// 編集(更新)
|
||||
Route::post('/{id}', [\App\Http\Controllers\Admin\CityController::class, 'update'])
|
||||
->whereNumber('id')
|
||||
->name('cities.update');
|
||||
|
||||
// 削除(複数削除 pk[])
|
||||
Route::post('/delete', [\App\Http\Controllers\Admin\CityController::class, 'destroy'])
|
||||
->name('cities.destroy');
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// 駐輪場マスタ
|
||||
Route::get('/parks', [ParkController::class, 'list'])->name('parks');
|
||||
|
||||
Loading…
Reference in New Issue
Block a user