W końcu wybrałem system, który generował znaczniki czasu dla daty rozpoczęcia i zakończenia w bazie danych. Podczas sprawdzania dodałem jedną sekundę do początku i odjąłem jedną sekundę od końca, aby uniknąć nakładania się czasu na spotkania.
Co w końcu zrobiłem
Oczywiście nie jestem pewien, czy to najlepsza praktyka, ale dla mnie zadziałała. Użytkownik zaczyna od wyboru płci i preferencji na dany dzień. Powoduje to wysłanie prośby AJAX o uzyskanie dostępnego personelu i różnego rodzaju spotkań (np. farbowanie włosów, strzyżenie włosów itp.).
Po wybraniu wszystkich ustawień (płeć, data, osoba i typ) zaczynam od kilku prostych walidacji:sprawdzenie daty, sprawdzenie, czy data ("N") nie jest 7 (niedziela). Jeśli wszystko jest w porządku, zaczynają się ważniejsze rzeczy:
1) Typ spotkania jest pobierany z bazy danych, w tym całkowity czas, jaki zajmuje ten typ (30 minut, 45 minut itp.)2) Dostępne dane osobowe są pobierane (pełna lista osób w tym dniu lub tylko jedna osoba, jeśli jeden jest wybrany) wraz z dostępnymi godzinami
Personel (lub jedna osoba) jest następnie zapętlony, zaczynając od własnego czasu rozpoczęcia. W tym momencie mam zestaw danych zawierający:
$duration (of the appointment type)
$startTime (starting time of the person selected in the loop)
$endTime (= $startTime + $duration)
$personStart (= starting time of the person)
$personEnd (= end time of the person)
Weźmy te dane demonstracyjne:
$duration = 30 min
$startTime = 9.00h
$endTime = 9.30h
$personStart = 9.00h
$personEnd = 12.00h
To, co tutaj robię, to:
while( $endTime < $personEnd )
{
// Check the spot for availability
$startTime = $endTime;
$endTime = $startTime + $duration;
}
Oczywiście w tym przypadku jest to uproszczone. Bo kiedy sprawdzam dostępność, a miejsce nie jest wolne. Ustawiam $startTime tak, aby był równy ostatniemu znalezionemu spotkaniu i zaczynam od tego miejsca w pętli.
Przykład:
I check for a free spot at 9.00 but the spot is not free because there's an appointment from 9.00 till 10.00, then 10.00 is returned and $startTime is set to 10.00h instead of 9.30h. This is done to keep the number of queries to a minimum since there can be quiet a lot.
Sprawdź funkcję dostępności
// Check Availability
public static function checkAvailability($start, $end, $ape_id)
{
// add one second to the start to avoid results showing up on the full hour
$start += 1;
// remove one second from the end to avoid results showing up on the full hour
$end -= 1;
// $start and $end are timestamps
$getAppointments = PRegistry::getObject('db')->query("SELECT * FROM appointments WHERE
((
app_start BETWEEN '".date("Y-m-d H:i:s", $start)."' AND '".date("Y-m-d H:i:s", $end)."'
OR
app_end BETWEEN '".date("Y-m-d H:i:s", $start)."' AND '".date("Y-m-d H:i:s", $end)."'
)
OR
(
app_start < '".date("Y-m-d H:i:s", $start)."' AND app_end > '".date("Y-m-d H:i:s", $end)."'
))
AND
ape_id = ".PRegistry::getObject('db')->escape($ape_id));
if(PRegistry::getObject('db')->num_rows($getAppointments) == 0) {
return true;
} else {
$end = 0;
foreach(PRegistry::getObject('db')->fetch_array(MYSQLI_ASSOC, $getAppointments, false) as $app) {
if($app['app_end'] > $end) {
$end = $app['app_end'];
}
}
return $end;
}
}
Ponieważ zapisuję terminy jako "Od:10.00 do:11.00" muszę pilnować, aby sprawdzać miejsca od 11:00:01 do 11:59:59, bo inaczej spotkanie o godzinie 11:00 pokaże się w wynikach.
Na końcu funkcji, w przypadku znalezienia spotkania, zapętlam wyniki i zwracam ostatni koniec. To kolejny początek pętli, o której wspomniałem powyżej.
Mam nadzieję, że może to pomóc każdemu. Podobnie jak informacje:ape_id
to identyfikator „osoby umówionej”, z którą jest powiązany.