PHP / Yii2 Check if at least 1 place in database is free for enough time before register

Ok, i think i was totally wrong… i tried a simple way to do it…

it is still not working, but i think it comes from somewhere about the date time (0000-00-00 00:00:00)
in inscriptions and in my array_of_time where it is only hours (00:00:00)

see code :
if anyone can help me to handle this ‘’

$sessionsInside = Session::find()->where(['>=', 'start_date', $today])->orderby(['start_date'=>'ASC'])->all(); //session ex: 2018-09-09 9h00 to 11h45
$inscriptionsInside = Inscription::find()->where(['>=', 'day', $today])->orderby(['day'=>'ASC'])->all();

foreach ($sessionsInside as $session) {

    $array_of_time = [];
    $place_count = 2;
    $session_id = $session->id;
    $session_start_day = $session->start_date; //  day of session 
    $session_start_time    = strtotime ($session->start_time); //start time of sesion 9h00
    $session_end_time      = strtotime ($session->end_time);  //end time of session 11h45
    $session_start_daytime =  $session_start_day.' '.date('H:i:s', $session_start_time);
    
    $fifteen_mins  = 15 * 60;

    while ($session_start_time <= $session_end_time) {
        
        $array_of_time[] = $session_start_time;      

        $session_start_time += $fifteen_mins;

    }


    foreach ($array_of_time as $start_time_session) {

        $end_time_session = $start_time_session + $duration_test;

        foreach ($inscriptionsInside as $inscription) {

            if($inscription->start_time == $start_time_session){
               // $array_of_time[] = unset($start_time_session);
                $array_of_time = array_diff($array_of_time, $start_time_session);
            }

            elseif($inscription->start_time > $start_time_session){
                if($inscription->start_time < $end_time_session){
                    $array_of_time = array_diff($array_of_time, $start_time_session);
                }
            }
            elseif($inscription->start_time < $start_time_session){
                if($inscription->end_time > $start_time_session){
                    $array_of_time = array_diff($array_of_time, $start_time_session);
                }

            }


        }
        
    }


    echo '<br>'.$session_start_day.'<br><br>';

    foreach ($array_of_time as $timeslot) {

        echo date('H:i',$timeslot).'<br>';
    

    }


}

I see in your code that’s something you’re doing wrong.

$array_of_test_time[] = [date('H:i',$new_start_time) => date('H:i',$end_test_time)];

In the foreach loop, you’re using $array_of_test_time is as wrong.

foreach ($array_of_test_time as $start => $end) {
    $arrayPcOne = Place::find()->where(['pc'=>'1','session_id' => $sessionId, 'start_time' => $new_start_time])->exists();
    //$arrayPcTwo etc etc until 6 ????

    $new_start_time = $new_start_time + 15;
}

Either you should change the creation of array or the foreach loop.

$array_of_test_time[date('H:i',$new_start_time)] = date('H:i',$end_test_time);

Give me more explanation for the code below,

foreach ($array_of_test_time as $start => $end) {
    $arrayPcOne = Place::find()->where(['pc'=>'1','session_id' => $sessionId, 'start_time' => $new_start_time])->exists();
   //$arrayPcTwo etc etc until 6 ????

   $new_start_time = $new_start_time + 15;
}

foreach ($totalarray as $date => $timevalue) {
    echo "<b>{$date}</b><br>";

    foreach ($timevalue as $key => $value) {
         echo $value['testtime'].'<br>';
    }
}

Hello @shifrin !

First, thank you very much for your help !

I will change the $array_of_test_time[] as you say, it’s much better!

The foreach of this array_of_test_time is maybe not the correct way to do what i would.

We have the $array_of_time given for each session.
(It should looks like :

  • 2018-09-28 09:00:00
  • 2018-09-28 09:15:00
  • 2018-09-28 09:30:00
    … until 11:45:00 )

and from this array, we take away the hour used by an inscription

$inscriptionInside = Inscription::find()->where( [ 'session_id' => $sessionId, 'start_time' => $start_daytime ] )->exists();
if(empty($inscriptionInside)){
            $array_of_time[] = $start_daytime;      
        }

Then, i need to find the way to test if at least 1 of 6 places is free for the duration given by the user :

This second array : $array_of_test_time give me the end time (which is the start time + duration)

But maybe we don’t need this array, maybe i thinking the wrong way.

I have a table : place

My idea was, foreach time in $array_of_time, to check in the table place if at least 1 place on 6 is free enough time. But i just can’t imagine how to do this…

And when i save a inscription, the table place would be “complete” like this :

if save 1 place at 9h00 for 1hour
table place : (pc1 is for place1, pc2 for place2 etc)

id | pc1 | client_id | inscription_id | session_id | 9h00
id | pc1 | client_id | inscription_id | session_id | 9h15
id | pc1 | client_id | inscription_id | session_id | 9h30
id | pc1 | client_id | inscription_id | session_id | 9h45

What i can do too, is :

    $arrayPcOne = Place::find()->where(['pc'=>'1','session_id' => $sessionId])->all();
    echo 'var dump pcone<br>';
    var_dump($arrayPcOne);

   foreach ($arrayPcOne as $place) {
       echo $place->pc.' - '.$place->start_time; // result : 1 - 10:00:0 01 - 10:15:0 01 - 10:30:0 01 - 10:45:00
   }

to get all used time on place 1, or if we delete the ‘pc’=>‘1’, we can get the array(object) for all 6 places used.

But then, i don’t know how to use this to do what i need…

I thought about something :

EDIT:

For now, i add datas in the database directly in phpMyAdmin, the exemple assume that data are already inside. When i will be able to have the array of available hours, i will make a form to get the datas and

  • save clients data (table client)
  • save inscription (table inscription)
  • save places (table place)

( ex : if somebody take a place from 10h00 to 10h45, one entry by slot of 15min will be save :

  • id | pc1 | client_id | inscription_id | session_id | 10h00
  • id | pc1 | client_id | inscription_id | session_id | 10h15
  • id | pc1 | client_id | inscription_id | session_id | 10h30
  • id | pc1 | client_id | inscription_id | session_id | 10h45

I am trying to check if at least 1 of 6 places is free for a duration given.

Ex: someone want to use a place for 1h.

A) i render an array of hours for each possible day (9h00 - 9h15 - 9h30… -> 11h45)

B) i check if any inscription is allready in the database and take it out
– ex: 9h30 is already took)

c) i need to check for the hours which still be in the array, if at least 1 of 6 places is free from this hour to end of duration
– ex: check if from 9h00 to 10h00 1 pc is free, check if from 9h15 to 10h15… etc

d) i need to render the final array with only the free and possible time to do the test.

Parts A and B are done, see code below. I’m stuck on C) part, if anyone can help me, maybe it’s not how it should be done, i’m open to any suggestion too.


Session table : id | start_date | start_time | end_time

place table : id | pc | slot | client_id | inscription_id | session_id | start_time

<?php
tests = Test::find()->all();

$price = 0;
$slots = 0;
$duration = 0;

foreach ($model->type as $testid) {                              
    foreach ($tests as $test) {                              
         if($test->id == $testid){
             echo $test->brand.' - ';
             echo $test->type.'<br>';
             $duration = $duration + (int)$test->duration;
             //duration of the test
                            
             $slots = $slots + (int)$test->slot_time;
             //time slots (ex: X * 15min)
                            
             $price = $price + (int)$test->price;
             //price of the test
                                    
             if($price > 220){ $price = 220;}
          }
     }
 }
                 
 $today = date('Y-m-d',strtotime("+10 days"));
 echo 'Duration: '.$duration.' min<br>';
 echo 'Slots: '.$slots.'<br>';
 echo 'Price: CHF '.$price.'.-<br>';      
 echo 'Day: '.date("d M Y", strtotime($today)).'<br><br><br>';

 //PART A - PART A - PART A                    
 $sessionsInside = Session::find()->where(['>=', 'start_date', $today])->orderby(['start_date'=>'ASC'])->all();
//session ex: 2018-09-09 9h00 to 11h45

foreach ($sessionsInside as $sessionday) {

$totalarray = [];
$array_of_time = [];
$array_of_test_time = [];

$sessionId = $sessionday->id;
$start_day = $sessionday->start_date; //  day of session 
$start_time = strtotime ($sessionday->start_time); //start time of sesion 9h00
$end_time = strtotime ($sessionday->end_time);  //end time of session 11h45
$fifteen_mins  = 15 * 60;
            	
while ($start_time <= $end_time)
{
     $start_daytime['testtime'] =  $start_day.' '.date('H:i:s', $start_time);
     
//PART B - PART B - PART B
$inscriptionInside = Inscription::find()->where( [ 'session_id' => $sessionId, 'start_time' => $start_daytime ] )->exists();

$new_start_time = $start_time;
$end_test_time =  strtotime(' + '.$duration.' minutes',$new_start_time);
//end time of the test ex : if start time is 9h00 and test duration is 1h00 - end_test_time is 10h00

//echo "start :".date('H:i',$new_start_time)." <br>";
//echo "end :".date('H:i', $end_test_time)." <br>";

$array_of_test_time[] = [date('H:i',$new_start_time) => date('H:i',$end_test_time)];

/*
   var_dump $array_of_test_time:
   array(12)
   {
       [0]=> array(1) {
                      ["09:00"]=> string(5) "10:30"
                      }
       [1]=> array(1) {
                      ["09:15"]=> string(5) "10:45"
                      }
       [2]=> array(1) {
                      ["09:30"]=> string(5) "11:00"
                      }
                     ....... 
    }
    */      

    if(empty($inscriptionInside)){
      $array_of_time[] = $start_daytime; //.' '.date('H:i:s',$start_time);      
    }
                           
    $start_time += $fifteen_mins;
}
                    
$totalarray = [$start_day => $array_of_time];

// END PART B - END PART B - END PART B

    
// PART C - PART C - PART C                 
foreach ($array_of_test_time as $start => $end) {

    $arrayPcOne = Place::find()->where(['pc'=>'1','session_id' => $sessionId, 'start_time' => $new_start_time])->exists();
//$arrayPcTwo etc etc until 6 ????

    $new_start_time = $new_start_time + 15;
}

foreach ($totalarray as $date => $timevalue) {
        echo "<b>{$date}</b><br>";
        foreach ($timevalue as $key => $value) {
                 echo $value['testtime'].'<br>';
        }
}

                    /*
                    2018-09-28
                    2018-09-28 09:00:00
                    2018-09-28 09:15:00
                    2018-09-28 09:30:00
                    2018-09-28 09:45:00
                    2018-09-28 10:15:00
                    2018-09-28 10:30:00
                    2018-09-28 10:45:00
                    2018-09-28 11:00:00
                    2018-09-28 11:30:00
                    2018-09-28 11:45:00
                    */

                    /*
                    2018-10-26
                    2018-10-26 09:00:00
                    2018-10-26 09:15:00
                    2018-10-26 09:30:00
                    2018-10-26 09:45:00
                    2018-10-26 10:00:00
                    2018-10-26 10:15:00
                    2018-10-26 10:30:00
                    2018-10-26 10:45:00
                    2018-10-26 11:00:00
                    2018-10-26 11:15:00
                    2018-10-26 11:30:00
                    2018-10-26 11:45:00
                    */
                }

            ?>

I can get the time used by place like this

    $arrayPlaces = Place::find()->where(['session_id' => $sessionId])->all();
    echo 'var dump places<br>';
    var_dump($arrayPlaces);

   foreach ($arrayPlaces as $place) {
       echo $place->pc.' - '.$place->start_time; 
   }

The $arrayPcOne will be place objects used. I don’t know if it can be used to find the solution.

Maybe i should do something like this ? :
session_start_time would come from $start_time with 15min ecrase,
$duration is given from the user at begining
$place_start_time is the start_time in place table

What do you think ?

if(empty($inscriptionInside)){

            if($session_start_time + $duration > $place_start_time ) {
                 $array_of_time[] = $start_daytime;
            }

        }