I have a script that allows me to automatically generate slots on a calendar according to the different opening hours of my users.
Today, I would like to improve the execution of my script to make it much faster than today (it takes a few seconds to make the calendar appear).
You have to know that I have a table OPENING_TIMES which contains 7 rows (1 per day) for each user.
I tried some improvements but without success (with joins for example).
Do you have any ideas?
Thanks in advance !
$Sch_Link_User  = $_GET['psy'];
$Data_query = mysqli_query($_Db_Con, 'SELECT ID_UNIQUE, CONSULTATION_TIME, CONSULTATION_TIME_BEFORE, TIMEZONE FROM USERS WHERE PROFILE_URL LIKE "' . $Sch_Link_User . '"');
$Data       = mysqli_fetch_assoc($Data_query);
$Sch_Id_User    = $Data['ID_UNIQUE'];
$Difference = '0';
switch ($Data['CONSULTATION_TIME']) {
    case 1:
        $Sch_Time_Consultation = 30;
        break;
    case 2:
        $Sch_Time_Consultation = 45;
        break;
    case 3:
        $Sch_Time_Consultation = 60;
        break;
    default:
        $Sch_Time_Consultation = 60;
}
$Calendar = array();
$weekslots = array_map(function($dow) {return array('dow' => $dow, 'hour' => 00);}, range(0, 6));
$date = time();
$end_date = $date + (6 * 7 * 24 * 60 * 60);
$open_hours_cache = array();
while($date <= $end_date) {
    $date_dow = date('w', $date);
    foreach($weekslots as $timeslot) {
        if($date_dow == $timeslot['dow']) {
            $timeofday = $date + (3600 * $timeslot['hour']);
            for($nd = 1; $nd <= 7; $nd++) {
                if(date('N', $timeofday) == $nd) {
                    if (!isset($open_hours_cache[$nd])) {
                        $Data_Openhours_query = mysqli_query($_Db_Con, 'SELECT START_HOUR_M, END_HOUR_M, START_HOUR_A, END_HOUR_A FROM OPENING_TIMES WHERE ID_USER = "' . $Sch_Id_User . '" AND WEEKDAY = "' . $nd . '" AND CLOSED = 0');
                        $open_hours_cache[$nd] = mysqli_fetch_assoc($Data_Openhours_query);
                    }
                    $Data_Openhours = $open_hours_cache[$nd];
                    if(isset($Data_Openhours['START_HOUR_M']) && $Data_Openhours['END_HOUR_M'] == NULL && $Data_Openhours['START_HOUR_A'] == NULL && isset($Data_Openhours['END_HOUR_A'])) {
                        $shm = strtotime($Data_Openhours['START_HOUR_M'] . $Difference . ' hour');
                        $eha = strtotime($Data_Openhours['END_HOUR_A'] . $Difference . ' hour');
                        
                        $timeslots = array();
                        $interval = new DateInterval("PT{$Sch_Time_Consultation}M");
                        $timeRange = new DatePeriod(new DateTime(date('Y-m-d H:i', $shm)), $interval, new DateTime(date('Y-m-d H:i', $eha)));
                        foreach ($timeRange as $time) {
                            $timeslots[] = $time->format("H:i");
                        }
                        foreach ($timeslots as $slot) {
                            $datefinal = date('Y-m-d', $timeofday) . ' ' . $slot . ':00';
                            $timestamp = strtotime($datefinal . $Difference . ' hour');
                        
                            $Check_Slot = mysqli_query($_Db_Con, 'SELECT ID, ID_USER, STATUS FROM APPOINTMENTS WHERE ID_USER = "' . $Sch_Id_User . '" AND DATE_START = "' . $timestamp . '" AND (STATUS = 1 OR STATUS = 2 OR STATUS = 9 OR STATUS = 10) AND DATE_START > "' . $Time . '"');
                            $Data_Slot = mysqli_fetch_assoc($Check_Slot);
                            $status = isset($Data_Slot['STATUS']) && $Data_Slot['STATUS'] == 9 && $Data_Slot['ID_USER'] == $_SESSION['uid'];
                            $check_slot = mysqli_num_rows($Check_Slot) == 0;
                            $time_before = ($Time + (60 * 60 * $Data['CONSULTATION_TIME_BEFORE'])) < $timestamp;
                        
                            if ($status) {
                                $class = 'blocked';
                            } elseif ($check_slot && $time_before) {
                                $class = 'available';
                            } else {
                                $class = 'unavailable';
                            }
                        
                            $Calendar[] = array(
                                'id' => date('Y-m-d', $timeofday) . '/' . $slot,
                                'title' => $slot,
                                'class' => $class,
                                'psy' => $Sch_Id_User,
                                'start' => $timestamp . '000',
                            );
                        }
                    } else if(isset($Data_Openhours['START_HOUR_M']) && isset($Data_Openhours['END_HOUR_M']) && isset($Data_Openhours['START_HOUR_A']) && isset($Data_Openhours['END_HOUR_A'])) {
                        $shm = strtotime($Data_Openhours['START_HOUR_M'] . $Difference . ' hour');
                        $ehm = strtotime($Data_Openhours['END_HOUR_M'] . $Difference . ' hour');
                        
                        $sha = strtotime($Data_Openhours['START_HOUR_A'] . $Difference . ' hour');
                        $eha = strtotime($Data_Openhours['END_HOUR_A'] . $Difference . ' hour');
                        
                        $timeslots = array();
                        $interval = new DateInterval("PT{$Sch_Time_Consultation}M");
                        
                        $timeRange = new DatePeriod(new DateTime(date('Y-m-d H:i', $shm)), $interval, new DateTime(date('Y-m-d H:i', $ehm)));
                        foreach ($timeRange as $time) {
                            $timeslots[] = $time->format("H:i");
                        }
                        $timeRange = new DatePeriod(new DateTime(date('Y-m-d H:i', $sha)), $interval, new DateTime(date('Y-m-d H:i', $eha)));
                        foreach ($timeRange as $time) {
                            $timeslots[] = $time->format("H:i");
                        }
                        foreach ($timeslots as $slot) {
                            $datefinal = date('Y-m-d', $timeofday) . ' ' . $slot . ':00';
                            $Check_Slot = mysqli_query($_Db_Con, 'SELECT ID, ID_USER, STATUS FROM APPOINTMENTS WHERE ID_USER = "' . $Sch_Id_User . '" AND DATE_START = "' . strtotime($datefinal) . '" AND (STATUS = 1 OR STATUS = 2 OR STATUS = 9 OR STATUS = 10) AND DATE_START > "' . $Time . '"');
                            $Data_Slot = mysqli_fetch_assoc($Check_Slot);
                            
                            // * 24 le temps avant possibilité de prende rendez-vous
                            $status = isset($Data_Slot['STATUS']) && $Data_Slot['STATUS'] == 9 && $Data_Slot['ID_USER'] == $_SESSION['uid'];
                            $check_slot = mysqli_num_rows($Check_Slot) == 0;
                            $time_before = ($Time + (60 * 60 * $Data['CONSULTATION_TIME_BEFORE'])) < strtotime($datefinal . $Difference . ' hour');
                            if ($status) {
                                $class = 'blocked';
                            } elseif ($check_slot && $time_before) {
                                $class = 'available';
                            } else {
                                $class = 'unavailable';
                            }
                            $Calendar[] = array(
                                'id' => date('Y-m-d', $timeofday) . '/' . $slot,
                                'title' => $slot,
                                'class' => $class,
                                'psy' => $Sch_Id_User,
                                'start' => strtotime($datefinal . $Difference . ' hour') . '000',
                            );
                        }
                    }
                }
            }
        }
    }
    
    $date += 86400;
}
$Calendar_Data = array(
    'success'   => 1,
    'result'    => $Calendar);
echo json_encode($Calendar_Data);
So I try to have a much faster loading with joins or a cache system to limit the number of requests.
Moreover, wouldn't it be more efficient if I also put everything in one column of my user table, the schedules?
