查询以从约会中获取可用时段 table
Query to get available slot from appointments table
我有employees, working_hours, & appointments
table。具有以下详细信息:
Employees | working_hours | appointment
id, name | id, day, start_time, end_time, employeeable_id, employeeable_type | id, employee_id, start_date_time, end_date_time
关系:
class Employee extends Model
{
public function workingHours()
{
return $this->morphMany(WorkingHour::class, 'employeeable');
}
}
class WorkingHour extends Model
{
public function employeeable()
{
return $this->morphTo();
}
}
class Appointment extends Model
{
public function employee()
{
return $this->belongsTo(Employee::class);
}
}
员工 A 的工作时间如下:
[
{ day: 1, start_time: '08:00:00', end_time: '17:00:00' },
...
{ day: 5, start_time: '08:00:00', end_time: '17:00:00 }
]
员工 A 有一个约会 2022 年 5 月 23 日 09:00:00 到 09:30: 00(每次预约时间为30分钟)
问题:
如果管理员请求从 2022 年 5 月 22 日 到 2022 年 6 月 1 日 员工 A,我期待这样的回应:
[
{ '2022-05-22': ['08:00', '08:30', '09:00', ..., '17:00'] },
{ '2022-05-23': ['08:00', '08:30', '09:30'] } // 09:00 notice excluded.
...
{ '2022-06-01, [] }
]
如何定义上述查询?我能想到的就是从员工 A 每隔 工作时间循环一次,并检查时间是否可用。
我建议你不要用查询来处理时间。
这是我的解决方案:
public function index()
{
$appointment = [
'id' => 1,
'name' => 'Appointment 1',
'start_date_time' => '2022-05-23 09:00:00',
'end_date_time' => '2022-05-23 09:30:00'
];
// Employee A working hours
$workingHours = collect([
['day' => 1, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 2, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 3, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 4, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 5, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 6, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 0, 'start_time' => '08:00:00', 'end_time' => '17:00:00'], // carbon for sunday default is 0
]);
$dateArray = [];
$startDate = Carbon::parse('2022-05-22');
$endDate = Carbon::parse('2022-06-01');
while ($startDate->lte($endDate)) {
// seach for working hours that match the day of the week
$workingHour = (array) $workingHours->firstWhere('day', $startDate->dayOfWeek);
// generate time for each day
$times = $this->generateTimes($workingHour);
// extract date from appoint start date time
$appointmentDate = Carbon::parse($appointment['start_date_time'])->format('Y-m-d');
if ($appointmentDate === $startDate->format('Y-m-d')) {
// remove time according to appointment time
$times = $this->removeTime($times, $appointment);
}
// add time to date array
$dateArray[$startDate->format('Y-m-d')] = $times;
// increment date
$startDate->addDay();
}
dd($dateArray);
}
private function generateTimes(array $workingHour)
{
// the working time of the workers must be reduced by at least 1 hour.
// because there is no way for you to have an appointment on your end working time.
$startTime = Carbon::parse($workingHour['start_time']);
$endTime = Carbon::parse($workingHour['end_time'])->subHour();
$times = [];
while ($startTime->lte($endTime)) {
$times[] = $startTime->format('H:i');
$startTime->addMinutes(30);
}
return $times;
}
private function removeTime($times, $appointment)
{
$startTime = Carbon::parse($appointment['start_date_time']);
$endTime = Carbon::parse($appointment['end_date_time']);
$startTime = $startTime->format('H:i');
$endTime = $endTime->format('H:i');
$times = array_diff($times, [$startTime, $endTime]);
return $times;
}
我有employees, working_hours, & appointments
table。具有以下详细信息:
Employees | working_hours | appointment
id, name | id, day, start_time, end_time, employeeable_id, employeeable_type | id, employee_id, start_date_time, end_date_time
关系:
class Employee extends Model
{
public function workingHours()
{
return $this->morphMany(WorkingHour::class, 'employeeable');
}
}
class WorkingHour extends Model
{
public function employeeable()
{
return $this->morphTo();
}
}
class Appointment extends Model
{
public function employee()
{
return $this->belongsTo(Employee::class);
}
}
员工 A 的工作时间如下:
[
{ day: 1, start_time: '08:00:00', end_time: '17:00:00' },
...
{ day: 5, start_time: '08:00:00', end_time: '17:00:00 }
]
员工 A 有一个约会 2022 年 5 月 23 日 09:00:00 到 09:30: 00(每次预约时间为30分钟)
问题:
如果管理员请求从 2022 年 5 月 22 日 到 2022 年 6 月 1 日 员工 A,我期待这样的回应:
[
{ '2022-05-22': ['08:00', '08:30', '09:00', ..., '17:00'] },
{ '2022-05-23': ['08:00', '08:30', '09:30'] } // 09:00 notice excluded.
...
{ '2022-06-01, [] }
]
如何定义上述查询?我能想到的就是从员工 A 每隔 工作时间循环一次,并检查时间是否可用。
我建议你不要用查询来处理时间。 这是我的解决方案:
public function index()
{
$appointment = [
'id' => 1,
'name' => 'Appointment 1',
'start_date_time' => '2022-05-23 09:00:00',
'end_date_time' => '2022-05-23 09:30:00'
];
// Employee A working hours
$workingHours = collect([
['day' => 1, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 2, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 3, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 4, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 5, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 6, 'start_time' => '08:00:00', 'end_time' => '17:00:00'],
['day' => 0, 'start_time' => '08:00:00', 'end_time' => '17:00:00'], // carbon for sunday default is 0
]);
$dateArray = [];
$startDate = Carbon::parse('2022-05-22');
$endDate = Carbon::parse('2022-06-01');
while ($startDate->lte($endDate)) {
// seach for working hours that match the day of the week
$workingHour = (array) $workingHours->firstWhere('day', $startDate->dayOfWeek);
// generate time for each day
$times = $this->generateTimes($workingHour);
// extract date from appoint start date time
$appointmentDate = Carbon::parse($appointment['start_date_time'])->format('Y-m-d');
if ($appointmentDate === $startDate->format('Y-m-d')) {
// remove time according to appointment time
$times = $this->removeTime($times, $appointment);
}
// add time to date array
$dateArray[$startDate->format('Y-m-d')] = $times;
// increment date
$startDate->addDay();
}
dd($dateArray);
}
private function generateTimes(array $workingHour)
{
// the working time of the workers must be reduced by at least 1 hour.
// because there is no way for you to have an appointment on your end working time.
$startTime = Carbon::parse($workingHour['start_time']);
$endTime = Carbon::parse($workingHour['end_time'])->subHour();
$times = [];
while ($startTime->lte($endTime)) {
$times[] = $startTime->format('H:i');
$startTime->addMinutes(30);
}
return $times;
}
private function removeTime($times, $appointment)
{
$startTime = Carbon::parse($appointment['start_date_time']);
$endTime = Carbon::parse($appointment['end_date_time']);
$startTime = $startTime->format('H:i');
$endTime = $endTime->format('H:i');
$times = array_diff($times, [$startTime, $endTime]);
return $times;
}