Php Laravel是介于开始和结束之间的时间;结束(防止重复预订)
我正在编写测试,以确保新预订不能被重复预订。我读过无数其他的SO帖子,现在我更困惑了,不确定自己做得对不对。我在我的项目和这个例子中特别使用了Laravel Migration.phpPhp Laravel是介于开始和结束之间的时间;结束(防止重复预订),php,mysql,laravel,datetime,Php,Mysql,Laravel,Datetime,我正在编写测试,以确保新预订不能被重复预订。我读过无数其他的SO帖子,现在我更困惑了,不确定自己做得对不对。我在我的项目和这个例子中特别使用了Laravel Migration.php ... $table->date('date'); // 2020-01-01 $table->time('time_start'); // 15:00:00 $table->time('time_end'); // 17:00:00 ... 'date' => date
...
$table->date('date'); // 2020-01-01
$table->time('time_start'); // 15:00:00
$table->time('time_end'); // 17:00:00
...
'date' => date('Y-m-d'),
'time_start' => '15:00:00',
'time_end' => '17:00:00',
...
$existing = DB::table('reservations')
->where('asset_id', '=', $request->asset_id)
->whereDate('date', '=', $request->date)
->whereTime('time_start', '>=', $request->time_start) // or use $request->strtotime('time_start')
->whereTime('time_end', '<=', $request->time_end)
->where(function ($query) {
$query
->where('status', '=', 'created')
->orWhere('status', '=', 'pending')
->orWhere('status', '=', 'completed');
})
->get();
if ($existing->count() > 0) {
// Not allowed
} else {
// OK to proceed
}
...
...
$http->assertStatus(400)
->assertJsonStructure([
'type', 'data' => [
'reason'
]])
->assertJson([
'type' => 'reservations',
'data' => [
'reason' => 'Asset is no longer available.',
],
]);
$asset = Asset::find($request->asset_id);
$existing = $asset->reservations()
->where(function ($query) use ($request) {
$start_dt = new Carbon($request->time_start);
$end_dt = new Carbon($request->time_end);
$query->where('time_start', '>=', $start_dt)
->where('time_end', '<=', $end_dt);
})
->whereIn('status', ['created', 'pending', 'completed'])
->get();
if ($existing->count() > 0) {
// Log::info('CANNOT MAKE RESERVATION FOR: ' . $request->first_name . ' ' . $request->last_name);
return response()->json(['type' => 'reservations', 'data' => ['reason' => 'Asset is no longer available.']], 409);
} else {
$reservation = new Reservation();
...
// Log::info('RESERVATION MADE FOR: ' . $reservation->first_name . ' ' . $reservation->last_name);
我曾经使用过dateTime
或timezone
。我陷入了一个陷阱,“我不需要日期,只需要时间。我正在将日期保存到其他地方。”然后,我会找到一个建议保存为时间戳的线程,并在那里比较日期
我有一个预订工厂要生成(除其他详细信息外)date
、time\u start
和time\u end
:
Factory.php
...
$table->date('date'); // 2020-01-01
$table->time('time_start'); // 15:00:00
$table->time('time_end'); // 17:00:00
...
'date' => date('Y-m-d'),
'time_start' => '15:00:00',
'time_end' => '17:00:00',
...
$existing = DB::table('reservations')
->where('asset_id', '=', $request->asset_id)
->whereDate('date', '=', $request->date)
->whereTime('time_start', '>=', $request->time_start) // or use $request->strtotime('time_start')
->whereTime('time_end', '<=', $request->time_end)
->where(function ($query) {
$query
->where('status', '=', 'created')
->orWhere('status', '=', 'pending')
->orWhere('status', '=', 'completed');
})
->get();
if ($existing->count() > 0) {
// Not allowed
} else {
// OK to proceed
}
...
...
$http->assertStatus(400)
->assertJsonStructure([
'type', 'data' => [
'reason'
]])
->assertJson([
'type' => 'reservations',
'data' => [
'reason' => 'Asset is no longer available.',
],
]);
$asset = Asset::find($request->asset_id);
$existing = $asset->reservations()
->where(function ($query) use ($request) {
$start_dt = new Carbon($request->time_start);
$end_dt = new Carbon($request->time_end);
$query->where('time_start', '>=', $start_dt)
->where('time_end', '<=', $end_dt);
})
->whereIn('status', ['created', 'pending', 'completed'])
->get();
if ($existing->count() > 0) {
// Log::info('CANNOT MAKE RESERVATION FOR: ' . $request->first_name . ' ' . $request->last_name);
return response()->json(['type' => 'reservations', 'data' => ['reason' => 'Asset is no longer available.']], 409);
} else {
$reservation = new Reservation();
...
// Log::info('RESERVATION MADE FOR: ' . $reservation->first_name . ' ' . $reservation->last_name);
我读过的大多数线程建议使用strttime
进行比较。比如:
'time_start' => strtotime('15:00:00'), // 1582210800
这是有道理的。但后来我读到,由于时区的原因,保存为dateTime
或timezone
更好
在我的控制器中,我正在检查现有的预订,如下所示:
Controller.php
...
$table->date('date'); // 2020-01-01
$table->time('time_start'); // 15:00:00
$table->time('time_end'); // 17:00:00
...
'date' => date('Y-m-d'),
'time_start' => '15:00:00',
'time_end' => '17:00:00',
...
$existing = DB::table('reservations')
->where('asset_id', '=', $request->asset_id)
->whereDate('date', '=', $request->date)
->whereTime('time_start', '>=', $request->time_start) // or use $request->strtotime('time_start')
->whereTime('time_end', '<=', $request->time_end)
->where(function ($query) {
$query
->where('status', '=', 'created')
->orWhere('status', '=', 'pending')
->orWhere('status', '=', 'completed');
})
->get();
if ($existing->count() > 0) {
// Not allowed
} else {
// OK to proceed
}
...
...
$http->assertStatus(400)
->assertJsonStructure([
'type', 'data' => [
'reason'
]])
->assertJson([
'type' => 'reservations',
'data' => [
'reason' => 'Asset is no longer available.',
],
]);
$asset = Asset::find($request->asset_id);
$existing = $asset->reservations()
->where(function ($query) use ($request) {
$start_dt = new Carbon($request->time_start);
$end_dt = new Carbon($request->time_end);
$query->where('time_start', '>=', $start_dt)
->where('time_end', '<=', $end_dt);
})
->whereIn('status', ['created', 'pending', 'completed'])
->get();
if ($existing->count() > 0) {
// Log::info('CANNOT MAKE RESERVATION FOR: ' . $request->first_name . ' ' . $request->last_name);
return response()->json(['type' => 'reservations', 'data' => ['reason' => 'Asset is no longer available.']], 409);
} else {
$reservation = new Reservation();
...
// Log::info('RESERVATION MADE FOR: ' . $reservation->first_name . ' ' . $reservation->last_name);
看起来它将被保存为time
列。在我的测试中,如果不能创建400
,我会检查是否返回了它
Test.php
...
$table->date('date'); // 2020-01-01
$table->time('time_start'); // 15:00:00
$table->time('time_end'); // 17:00:00
...
'date' => date('Y-m-d'),
'time_start' => '15:00:00',
'time_end' => '17:00:00',
...
$existing = DB::table('reservations')
->where('asset_id', '=', $request->asset_id)
->whereDate('date', '=', $request->date)
->whereTime('time_start', '>=', $request->time_start) // or use $request->strtotime('time_start')
->whereTime('time_end', '<=', $request->time_end)
->where(function ($query) {
$query
->where('status', '=', 'created')
->orWhere('status', '=', 'pending')
->orWhere('status', '=', 'completed');
})
->get();
if ($existing->count() > 0) {
// Not allowed
} else {
// OK to proceed
}
...
...
$http->assertStatus(400)
->assertJsonStructure([
'type', 'data' => [
'reason'
]])
->assertJson([
'type' => 'reservations',
'data' => [
'reason' => 'Asset is no longer available.',
],
]);
$asset = Asset::find($request->asset_id);
$existing = $asset->reservations()
->where(function ($query) use ($request) {
$start_dt = new Carbon($request->time_start);
$end_dt = new Carbon($request->time_end);
$query->where('time_start', '>=', $start_dt)
->where('time_end', '<=', $end_dt);
})
->whereIn('status', ['created', 'pending', 'completed'])
->get();
if ($existing->count() > 0) {
// Log::info('CANNOT MAKE RESERVATION FOR: ' . $request->first_name . ' ' . $request->last_name);
return response()->json(['type' => 'reservations', 'data' => ['reason' => 'Asset is no longer available.']], 409);
} else {
$reservation = new Reservation();
...
// Log::info('RESERVATION MADE FOR: ' . $reservation->first_name . ' ' . $reservation->last_name);
这很有效。如果我创建了一个从15:00:00
到17:00:00
相同日期/资产等的预订,我的测试通过。我得到的400错误完全符合我的预期。但是,如果我通过15:01:00
我的测试失败。这并不奇怪,但这说明我没有正确处理比较。看起来我就在终点线上,但后来两双鞋都解开了
用户界面只是一个下拉菜单,上面有人类可读的时间。我正计划将这些值保存为24小时时间。例如,15:00:00
。我不知道还能怎么做
如能提出建议,以便更好地了解:
- 最好节省时间
时间
,时间戳
,日期时间
- 使用
strotime
(或不使用)。如果是,理想的数据类型是什么<代码>时间戳
,日期时间
time\u start
和time\u end
保存为迁移中的dateTime
字段
Controller.php
...
$table->date('date'); // 2020-01-01
$table->time('time_start'); // 15:00:00
$table->time('time_end'); // 17:00:00
...
'date' => date('Y-m-d'),
'time_start' => '15:00:00',
'time_end' => '17:00:00',
...
$existing = DB::table('reservations')
->where('asset_id', '=', $request->asset_id)
->whereDate('date', '=', $request->date)
->whereTime('time_start', '>=', $request->time_start) // or use $request->strtotime('time_start')
->whereTime('time_end', '<=', $request->time_end)
->where(function ($query) {
$query
->where('status', '=', 'created')
->orWhere('status', '=', 'pending')
->orWhere('status', '=', 'completed');
})
->get();
if ($existing->count() > 0) {
// Not allowed
} else {
// OK to proceed
}
...
...
$http->assertStatus(400)
->assertJsonStructure([
'type', 'data' => [
'reason'
]])
->assertJson([
'type' => 'reservations',
'data' => [
'reason' => 'Asset is no longer available.',
],
]);
$asset = Asset::find($request->asset_id);
$existing = $asset->reservations()
->where(function ($query) use ($request) {
$start_dt = new Carbon($request->time_start);
$end_dt = new Carbon($request->time_end);
$query->where('time_start', '>=', $start_dt)
->where('time_end', '<=', $end_dt);
})
->whereIn('status', ['created', 'pending', 'completed'])
->get();
if ($existing->count() > 0) {
// Log::info('CANNOT MAKE RESERVATION FOR: ' . $request->first_name . ' ' . $request->last_name);
return response()->json(['type' => 'reservations', 'data' => ['reason' => 'Asset is no longer available.']], 409);
} else {
$reservation = new Reservation();
...
// Log::info('RESERVATION MADE FOR: ' . $reservation->first_name . ' ' . $reservation->last_name);
$asset=asset::find($request->asset\u id);
$existing=$asset->reservations()
->其中(函数($query)使用($request){
$start\u dt=新碳($request->time\u start);
$end\u dt=新碳($request->time\u end);
$query->where('time\u start','>=',$start\u dt)
->其中('time_end','您最好将此信息存储为两列DATETIME
。优点包括能够利用Laravel内置的碳日期转换功能,避免在午夜预订约会的麻烦
然后,假设$request->time\u start
和$request->time\u end
是完整的日期/时间,您的查询如下:
$existing=DB::table('reservations')
->其中('asset\u id',$request->asset\u id)
->在哪里(
fn($q)=>$q->whereBetween('time\u start',[$request->time\u start,$request->time\u end])
->或者两者之间('time\u end',[$request->time\u start,$request->time\u end])
->或者在哪里(
fn($q)=>$q->where('time\u start','',$request->time\u end);
)
)
->其中('状态',['已创建','待处理','已完成')
->get();
您还可以将time\u start
和time\u end
添加到模型的$dates
数组中,以充分利用它们
说到模型,如果您的关系设置正确,则此查询可能是这样的,而不是使用DB
facade:
$asset=asset::find($request->asset\u id);
$existing=$asset
->保留()
->在哪里(
fn($q)=>$q->whereBetween('time\u start',[$request->time\u start,$request->time\u end])
->或者两者之间('time\u end',[$request->time\u start,$request->time\u end])
->或者在哪里(
fn($q)=>$q->where('time\u start','',$request->time\u end)
)
)
->其中('状态',['已创建','待处理','已完成')
->get();
它并不短,但在我看来,它更容易一目了然地看到正在搜索的内容
至于HTTP响应,你使用什么并不重要。这都是你的代码,所以你知道应该期待什么。但是如果你想学究的话(我完全支持),也许可以满足你的需要
409(冲突)状态代码表示请求无法执行
由于与目标的当前状态冲突而无法完成
此代码用于用户可能是
能够解决冲突并重新提交请求。服务器
应该为用户生成包含足够信息的有效负载
认识到冲突的根源
您可能不想在这里进行比较,但是您需要检查两件事:开始或结束时间是否属于任何已存在的预订时间间隔;或者在现有预订时间间隔之前和之后开始(因为你不能在上午9点到14点进行新的预订,如果上午10点到11点已经存在的话。)400在这里不是一个真正合适的响应。引用Wikipedia的HTTP状态代码,“400错误请求-由于明显的客户端错误,服务器无法或不会处理请求(例如,请求语法格式错误、大小过大、请求无效)