質問編集履歴
5
コントローラーを調整
title
CHANGED
File without changes
|
body
CHANGED
@@ -117,19 +117,10 @@
|
|
117
117
|
}
|
118
118
|
```
|
119
119
|
|
120
|
-
#### Controller(自
|
120
|
+
#### Controller(自力で予約確定まで組んでみたものです)
|
121
121
|
```php
|
122
122
|
<?php
|
123
123
|
|
124
|
-
namespace App\Http\Controllers;
|
125
|
-
|
126
|
-
use App\Reserve;
|
127
|
-
use App\Exceptions\ReserveDuplicationException;
|
128
|
-
use App\Http\Requests\CreateReserveRequest;
|
129
|
-
use Carbon\Carbon;
|
130
|
-
use Illuminate\Http\Request;
|
131
|
-
|
132
|
-
|
133
124
|
class ReserveController extends Controller {
|
134
125
|
|
135
126
|
// フォームから受け取った情報をもとにテーブルを検索、施設名から施設IDを引っ張り、日付と合わせて予約情報を取得しAjaxに返す。
|
@@ -205,7 +196,7 @@
|
|
205
196
|
function isTimeDuplication($start, $end, $start_time, $end_time) {
|
206
197
|
return ($start < $end_time && $start_time < $end);
|
207
198
|
}
|
208
|
-
// try-catchで例外が出たら
|
199
|
+
// try-catchで例外が出たら入力フォームまでロールバックする。
|
209
200
|
|
210
201
|
try {
|
211
202
|
|
@@ -221,7 +212,7 @@
|
|
221
212
|
}
|
222
213
|
}
|
223
214
|
|
224
|
-
// 入力確認ページのviewに
|
215
|
+
// 入力確認ページのviewにdataを渡す
|
225
216
|
return view('reserve-confirm', [
|
226
217
|
'data' => $data,
|
227
218
|
]);
|
@@ -234,87 +225,99 @@
|
|
234
225
|
}
|
235
226
|
}
|
236
227
|
|
237
|
-
|
228
|
+
// 予約完了メールの発送
|
229
|
+
public function send(Request $request) {
|
238
230
|
|
239
|
-
|
231
|
+
//フォームから受け取ったactionの値を取得
|
232
|
+
$action = $request->input('action');
|
240
|
-
|
233
|
+
$inputs = $request->except('action');
|
241
234
|
|
235
|
+
//actionの値で分岐
|
242
|
-
|
236
|
+
if($action !== 'submit'){
|
243
|
-
|
237
|
+
return redirect()
|
244
|
-
|
238
|
+
->route('reserve.index')
|
245
|
-
|
239
|
+
->withInput($inputs);
|
246
240
|
|
241
|
+
} else {
|
242
|
+
$user = Auth::user();
|
247
|
-
|
243
|
+
$email = $user->email;
|
248
|
-
<select class="form-control" id="facility_name" name="facility_name">
|
249
|
-
<option value="blank" selected="selected">選択してください</option>
|
250
|
-
|
244
|
+
\Mail::to($email)->send(new ContactSendmail($inputs));
|
251
|
-
<option value="test2">test2</option>
|
252
|
-
<option value="test3">test4</option>
|
253
|
-
</select>
|
254
|
-
|
255
|
-
</div>
|
256
|
-
</div>
|
257
245
|
|
246
|
+
// トークンを再発行して再送信防止
|
247
|
+
|
258
|
-
|
248
|
+
$request->session()->regenerateToken();
|
259
|
-
<label for="dates" class="col-md-4 col-form-label text-md-right">{{ __('dates' )}}</label>
|
260
249
|
|
261
|
-
<div class="col-md-6">
|
262
|
-
<input type="text" class="form-control dateinfo" placeholder="Select Date.." id="dateinfo" name="dateinfo" readonly="readonly">
|
263
|
-
|
264
|
-
|
250
|
+
}
|
265
|
-
</div>
|
266
251
|
|
267
|
-
<div class="form-group row">
|
268
|
-
<div class="col-md-8 offset-md-4">
|
269
|
-
<button type="submit" class="btn btn-primary" data-action='javascript:void(0);' id="date-select">
|
270
|
-
|
252
|
+
}
|
271
|
-
</button>
|
272
|
-
|
273
|
-
</div>
|
274
|
-
</div>
|
275
253
|
|
276
|
-
<div class="form-group row js-timeselectform" >
|
277
|
-
<label for="start_time" class="col-md-4 col-form-label text-md-right">{{ __('start_time' )}}</label>
|
278
254
|
|
279
|
-
<div class="col-md-6">
|
280
|
-
<input type="text" class="form-control time" placeholder="Select Time.." id="start_time" name="start_time" readonly="readonly">
|
281
|
-
|
282
|
-
|
255
|
+
// 予約確定による、データベースへの情報の追加
|
283
|
-
</div>
|
284
256
|
|
285
|
-
|
257
|
+
public function store(Request $request) {
|
286
|
-
<label for="end_time" class="col-md-4 col-form-label text-md-right">{{ __('end_time' )}}</label>
|
287
258
|
|
288
|
-
<div class="col-md-6">
|
289
|
-
<input type="text" class="form-control time" placeholder="Select Time.." id="end_time" name="end_time" readonly="readonly">
|
290
|
-
|
291
|
-
|
259
|
+
// バリデーション
|
260
|
+
|
292
|
-
|
261
|
+
$request->validate([
|
262
|
+
'facility_name' => 'required',
|
263
|
+
'dateinfo' => 'required',
|
264
|
+
'start_time' => 'required',
|
265
|
+
'end_time' => 'required',
|
266
|
+
]);
|
293
267
|
|
294
|
-
|
268
|
+
|
295
|
-
<div class="col-md-8 offset-md-4">
|
296
|
-
<button type="submit" class="btn btn-primary" data-action="{{ route('reserve.confirm') }}" id="reserve-settle">
|
297
|
-
|
269
|
+
// 再度ダブルブッキングのチェックを行う。
|
298
|
-
</button>
|
299
|
-
</div>
|
300
|
-
</div>
|
301
|
-
</form>
|
302
|
-
</div>
|
303
|
-
</div>
|
304
|
-
<!-- 予約時間重複によるエラーメッセージ表示。仮置してます。 -->
|
305
|
-
@if ($errors->any())
|
306
|
-
<ul id = "error" class="error">
|
307
|
-
|
270
|
+
$this->confirm($request);
|
308
271
|
|
309
|
-
|
272
|
+
// 以下、ダブルブッキングなしの場合の更新処理
|
310
273
|
|
311
|
-
@endforeach
|
312
|
-
|
274
|
+
//フォームから受け取ったactionを除いたinputの値を取得
|
313
|
-
|
275
|
+
$inputs = $request->except('action');
|
314
276
|
|
277
|
+
// 検索用にfacility_nameをのみ別に変数に取り出しておく
|
278
|
+
|
279
|
+
$facility_name = $inputs['facility_name'];
|
280
|
+
|
281
|
+
// facility_idを抽出するメソッド
|
282
|
+
|
283
|
+
$facility_id = Facility::SearchFacility_id($facility_name);
|
284
|
+
|
285
|
+
|
286
|
+
// dateinfoとstart_time及びend_timeを組み合わせてdatetime型にする。
|
287
|
+
$start_time =$inputs['dateinfo'] .' '. $inputs['start_time'];
|
288
|
+
$end_time =$inputs['dateinfo'] .' '. $inputs['end_time'];
|
289
|
+
|
290
|
+
// 予約番号生成
|
291
|
+
|
292
|
+
$reserve_number = uniqid(bin2hex(random_bytes((1))));
|
293
|
+
|
294
|
+
// ユーザー情報取得
|
295
|
+
$user = Auth::user();
|
296
|
+
$user_id = $user->id;
|
297
|
+
|
298
|
+
// データベースに追加
|
299
|
+
$reserve = new Reserve();
|
300
|
+
$reserve->user_id = $user_id;
|
301
|
+
$reserve->facility_id = $facility_id;
|
302
|
+
$reserve->start_time = $start_time;
|
303
|
+
$reserve->end_time = $end_time;
|
304
|
+
$reserve->reserve_number = $reserve_number;
|
305
|
+
$reserve->save();
|
306
|
+
|
307
|
+
\Debugbar::info();
|
308
|
+
|
309
|
+
$this->send($request);
|
310
|
+
|
311
|
+
// viewへ遷移
|
312
|
+
return view('reserve-complete' ,[
|
313
|
+
'reserve_number' => $reserve_number,
|
315
|
-
|
314
|
+
]);
|
315
|
+
}
|
316
|
+
|
316
317
|
```
|
317
318
|
|
319
|
+
|
320
|
+
|
318
321
|
## 質問に際してやったこと・作ったもの
|
319
322
|
|
320
323
|
####console.log一覧
|
4
ControllerとViewの更新とHandler.phpの追記
title
CHANGED
File without changes
|
body
CHANGED
@@ -21,10 +21,12 @@
|
|
21
21
|

|
22
22
|
|
23
23
|
このようなコードを書いて冒頭の画像の利用開始時刻と、利用終了時刻の選択内容をバインドしています。
|
24
|
-
ですが、
|
24
|
+
ですが、例えばこの場合利用開始に14:00、利用終了に18:00を選択して14:00~18:00の時間帯を予約したいというリクエストができてしまいます。
|
25
25
|
当然それでは前述の前提条件とバッティングしてしまうのでその場合、確認画面に遷移せずフォームにリダイレクトしてエラーメッセージを表示させたいのですがこの場合バリデーションでやるのか自分で独自例外を作成してtry-catchでその例外に投げるのかどちらにするのかがわからないのでお聞きしたいです。
|
26
|
-
本来なら無効な値ということでバリデーションでどうにかするのかな? という考えはあるのですが、上記の例の場合それぞれ利用開始・利用終了単独の値としては有効なので詰まってしまいました.......
|
27
26
|
|
27
|
+
2020/01/10
|
28
|
+
コメント欄でご指摘いただいた箇所を修正、かつ自分なりにエラーハンドリングをしてみたのでControllerにそれを反映。
|
29
|
+
|
28
30
|
以下コード他です。
|
29
31
|
|
30
32
|
#### AjaxでPHPから帰ってくる予約情報
|
@@ -48,7 +50,7 @@
|
|
48
50
|
```
|
49
51
|
|
50
52
|
#### バリデーション
|
51
|
-
とりあえず基本的なところだけ
|
53
|
+
とりあえず基本的なところだけ。rulesメソッドのみ抜粋。
|
52
54
|
|
53
55
|
```php
|
54
56
|
<?php
|
@@ -60,22 +62,7 @@
|
|
60
62
|
|
61
63
|
class CreateReserveRequest extends FormRequest
|
62
64
|
{
|
63
|
-
/**
|
64
|
-
* Determine if the user is authorized to make this request.
|
65
|
-
*
|
66
|
-
* @return bool
|
67
|
-
*/
|
68
|
-
public function authorize() {
|
69
65
|
|
70
|
-
// 認証関係のバリデーションはここ。なければtrueを返す。
|
71
|
-
return true;
|
72
|
-
}
|
73
|
-
|
74
|
-
/**
|
75
|
-
* Get the validation rules that apply to the request.
|
76
|
-
*
|
77
|
-
* @return array
|
78
|
-
*/
|
79
66
|
public function rules()
|
80
67
|
{
|
81
68
|
return [
|
@@ -97,8 +84,6 @@
|
|
97
84
|
namespace App;
|
98
85
|
|
99
86
|
use Illuminate\Database\Eloquent\Model;
|
100
|
-
use Webpatser\Uuid\Uuid;
|
101
|
-
use Katteba\UUID\UUIDShortener;
|
102
87
|
|
103
88
|
class Reserve extends Model {
|
104
89
|
public $incrementing = false;
|
@@ -111,14 +96,6 @@
|
|
111
96
|
|
112
97
|
];
|
113
98
|
|
114
|
-
protected static function boot () {
|
115
|
-
parent::boot();
|
116
|
-
|
117
|
-
static::creating(function ($model) {
|
118
|
-
$model->{$model->getKeyName()} = Uuid::generate()->string;
|
119
|
-
});
|
120
|
-
}
|
121
|
-
|
122
99
|
public function user() {
|
123
100
|
return $this->belongsTo('App\User');
|
124
101
|
}
|
@@ -140,7 +117,7 @@
|
|
140
117
|
}
|
141
118
|
```
|
142
119
|
|
143
|
-
#### Controller(
|
120
|
+
#### Controller(自分でtry-catchを組んでみました、全体としては未完成なので抜粋してます)
|
144
121
|
```php
|
145
122
|
<?php
|
146
123
|
|
@@ -322,13 +299,47 @@
|
|
322
299
|
</div>
|
323
300
|
</div>
|
324
301
|
</form>
|
302
|
+
</div>
|
303
|
+
</div>
|
304
|
+
<!-- 予約時間重複によるエラーメッセージ表示。仮置してます。 -->
|
305
|
+
@if ($errors->any())
|
306
|
+
<ul id = "error" class="error">
|
307
|
+
@foreach ($errors->all() as $error)
|
308
|
+
|
309
|
+
<li>{{ $error }}</li>
|
310
|
+
|
311
|
+
@endforeach
|
312
|
+
</ul>
|
313
|
+
@endif
|
314
|
+
|
315
|
+
(後略)
|
325
316
|
```
|
326
317
|
|
327
|
-
|
328
318
|
## 質問に際してやったこと・作ったもの
|
329
319
|
|
330
320
|
####console.log一覧
|
331
321
|

|
332
322
|
|
333
323
|
####定義しているテーブル
|
334
|
-

|
324
|
+

|
325
|
+
|
326
|
+
## 追記
|
327
|
+
|
328
|
+
####Handler.php
|
329
|
+
|
330
|
+
```php
|
331
|
+
|
332
|
+
public function prepareResponse($request, Exception $e) {
|
333
|
+
// 競合違反を条件分岐
|
334
|
+
if($e instanceof ConflictHttpException) {
|
335
|
+
return $this->invaildHttpRequest($request, $e);
|
336
|
+
}
|
337
|
+
// 予約時間が競合していた場合エラーハンドリング
|
338
|
+
if($e instanceof ReserveDuplicationException) {
|
339
|
+
return redirect()->back()->withInput()->withErrors('その時間帯はすでに予約が入っています');
|
340
|
+
}
|
341
|
+
|
342
|
+
return parent::prepareResponse($request, $e);
|
343
|
+
}
|
344
|
+
|
345
|
+
```
|
3
指摘を受けた箇所を修正。
title
CHANGED
File without changes
|
body
CHANGED
@@ -147,6 +147,7 @@
|
|
147
147
|
namespace App\Http\Controllers;
|
148
148
|
|
149
149
|
use App\Reserve;
|
150
|
+
use App\Exceptions\ReserveDuplicationException;
|
150
151
|
use App\Http\Requests\CreateReserveRequest;
|
151
152
|
use Carbon\Carbon;
|
152
153
|
use Illuminate\Http\Request;
|
@@ -159,7 +160,7 @@
|
|
159
160
|
|
160
161
|
$data = $request->all();
|
161
162
|
|
162
|
-
if(isset($
|
163
|
+
if(isset($data['dateinfo']) && isset($data['facility_name'])) {
|
163
164
|
|
164
165
|
$dateinfo = $data['dateinfo'];
|
165
166
|
$facility_name = $data['facility_name'];
|
@@ -179,39 +180,41 @@
|
|
179
180
|
public function confirm(CreateReserveRequest $request) {
|
180
181
|
|
181
182
|
// 予約情報取得
|
182
|
-
|
183
|
-
if(isset($_POST['dateinfo']) && isset($_POST['facility_name'])) {
|
184
183
|
|
185
|
-
$
|
184
|
+
$data = $request->all();
|
186
|
-
$facility_name = $_POST['facility_name'];
|
187
185
|
|
186
|
+
if(isset($data['dateinfo']) && isset($data['facility_name'])) {
|
187
|
+
|
188
|
+
$dateinfo = $data['dateinfo'];
|
189
|
+
$facility_name = $data['facility_name'];
|
190
|
+
|
188
191
|
$reserveinfo = Reserve::SearchReserveDates($facility_name, $dateinfo);
|
189
|
-
|
190
192
|
}
|
191
193
|
|
194
|
+
|
192
195
|
// 取得したレコードを配列の形にする。
|
193
196
|
// start_timeとend_timeそれぞれの値で配列を作る。
|
194
197
|
|
195
198
|
$arr_start_time = array_column($reserveinfo, 'start_time');
|
196
|
-
var_dump($arr_start_time);
|
199
|
+
// var_dump($arr_start_time);
|
197
200
|
$arr_end_time = array_column($reserveinfo, 'end_time');
|
198
|
-
var_dump($arr_end_time);
|
201
|
+
// var_dump($arr_end_time);
|
199
202
|
|
200
203
|
// 選択された時間帯が予約時間と重複していないか検証
|
201
|
-
if(isset($
|
204
|
+
if(isset($data['start_time']) && isset($data['end_time'])) {
|
202
205
|
|
203
206
|
// datetime型に整形
|
204
|
-
$start_datetime =$
|
207
|
+
$start_datetime =$data['dateinfo'] .' '. $data['start_time'];
|
205
|
-
$end_datetime =$
|
208
|
+
$end_datetime =$data['dateinfo'] .' '. $data['end_time'];
|
206
209
|
|
207
210
|
// Carbonに整形
|
208
211
|
|
209
212
|
$st = new Carbon($start_datetime);
|
210
213
|
$start = $st->format('Y-m-d H:i:s');
|
211
|
-
var_dump($start);
|
214
|
+
// var_dump($start);
|
212
215
|
$ed = new Carbon($end_datetime);
|
213
216
|
$end = $ed->format('Y-m-d H:i:s');
|
214
|
-
var_dump($end);
|
217
|
+
// var_dump($end);
|
215
218
|
// テーブルから予約情報取得して配列に格納
|
216
219
|
// それぞれ$arr_start_time[]と$arr_end_times[]で呼び出せるようにする
|
217
220
|
// forかwhile文で$start_time[n]と$end_time[n]まで検証する
|
@@ -220,46 +223,38 @@
|
|
220
223
|
$c1 = count($arr_start_time);
|
221
224
|
$c2 = count($arr_end_time);
|
222
225
|
|
226
|
+
|
223
|
-
/
|
227
|
+
// 時間帯比較の関数
|
224
|
-
以下の関数を用いてフォームで選択された時間と登録されている予約情報の時間とで
|
225
|
-
比較を行い、予約済みの時間帯と重複していた場合はエラーハンドリングを行いたい。
|
226
|
-
*/
|
227
228
|
function isTimeDuplication($start, $end, $start_time, $end_time) {
|
228
229
|
return ($start < $end_time && $start_time < $end);
|
229
230
|
}
|
231
|
+
// try-catchで例外が出たら処理中止する。
|
232
|
+
|
233
|
+
try {
|
230
234
|
|
231
|
-
// 予約情報の数だけ時間帯比較を行いたいと考えて以下のようなコードを書いた。
|
232
|
-
|
235
|
+
for ($i=0; $i < $c1 && $c2 ; $i++) {
|
233
236
|
|
234
237
|
$start_time = $arr_start_time[$i];
|
235
238
|
$end_time = $arr_end_time[$i];
|
236
239
|
|
237
240
|
$result = isTimeDuplication($start, $end, $start_time, $end_time);
|
238
241
|
|
239
|
-
// 時間帯比較がTRUE、つまり重複した時間帯があった場合エラーメッセージ、違うなら比較をを続行する。
|
240
|
-
if(isTimeDuplication($start, $end, $start_time, $end_time) === TRUE) {
|
241
|
-
echo 'error';
|
242
|
-
|
242
|
+
if($result === TRUE) {
|
243
|
-
|
243
|
+
throw new ReserveDuplicationException;
|
244
|
-
|
244
|
+
}
|
245
245
|
}
|
246
246
|
|
247
|
+
// 入力確認ページのviewにinputsを渡す
|
248
|
+
return view('reserve-confirm', [
|
249
|
+
'data' => $data,
|
250
|
+
]);
|
247
251
|
|
252
|
+
} catch(ReserveDuplicationException $e) {
|
253
|
+
throw $e;
|
248
254
|
}
|
249
255
|
|
250
|
-
// ここまで書いてもしかしたら、try-catchしたほうがいいけどその場合例外処理どうするのだろうと詰まりました。
|
251
256
|
|
252
|
-
// 以下は比較でいずれも例外が認められなかった場合の処理
|
253
|
-
|
254
|
-
//フォームから受け取ったすべてのinputの値を取得
|
255
|
-
$inputs = $request->all();
|
256
|
-
|
257
|
-
// 確認ページのviewにinputsを渡す
|
258
|
-
return view('reserve-confirm', [
|
259
|
-
'inputs' => $inputs,
|
260
|
-
]);
|
261
257
|
}
|
262
|
-
|
263
258
|
}
|
264
259
|
|
265
260
|
```
|
2
レイアウト修正
title
CHANGED
File without changes
|
body
CHANGED
@@ -332,7 +332,8 @@
|
|
332
332
|
|
333
333
|
## 質問に際してやったこと・作ったもの
|
334
334
|
|
335
|
+
####console.log一覧
|
335
|
-
|
336
|
+

|
336
337
|
|
337
|
-
定義しているテーブル
|
338
|
+
####定義しているテーブル
|
338
339
|

|
1
誤字修正
title
CHANGED
File without changes
|
body
CHANGED
@@ -28,7 +28,7 @@
|
|
28
28
|
以下コード他です。
|
29
29
|
|
30
30
|
#### AjaxでPHPから帰ってくる予約情報
|
31
|
-
ちなみにid3
|
31
|
+
ちなみにid3は2019-11-30とは別の日付の予約情報なので弾かれています。
|
32
32
|
```
|
33
33
|
{
|
34
34
|
"id": "1",
|