Reputation: 77
I'm trying to populate an array of array where room_id should be combined in one sub-array instead of separated like they currently are. Here is my code:
$query = "SELECT res_id, room_id, guest_id, check_in_date, check_out_date FROM reservation ";
$result = mysqli_query($link, $query) or die (mysqli_error($link));
$rooms = array();
while ($row = mysqli_fetch_assoc($result)) {
$rooms[] = $row;
}
$array_date = array();
foreach ($rooms as $room) {
$array_date[] = date_range($room['room_id'], $room['check_in_date'], $room['check_out_date']);
}
function date_range($room_id, $first, $last, $step = '+1 day', $output_format = 'Y-m-d' ) {
$room_date = array();
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
$room_date[$room_id] = $dates;
return $room_date;
}
Here is the result with var_dump:
Array
(
[0] => Array
(
[1] => Array
(
[0] => 2015-04-08
[1] => 2015-04-09
[2] => 2015-04-10
)
)
[1] => Array
(
[1] => Array
(
[0] => 2015-04-11
[1] => 2015-04-12
[2] => 2015-04-13
)
)
[2] => Array
(
[2] => Array
(
[0] => 2015-04-08
[1] => 2015-04-09
[2] => 2015-04-10
[3] => 2015-04-11
[4] => 2015-04-12
[5] => 2015-04-13
)
)
What I really want is this (same room_id combined in one array):
Array
(
[0] => Array
(
[1] => Array
(
[0] => 2015-04-08
[1] => 2015-04-09
[2] => 2015-04-10
[3] => 2015-04-11
[4] => 2015-04-12
[5] => 2015-04-13
)
)
[2] => Array
(
[2] => Array
(
[0] => 2015-04-08
[1] => 2015-04-09
[2] => 2015-04-10
[3] => 2015-04-11
[4] => 2015-04-12
[5] => 2015-04-13
)
)
)
I completely ran out of ideas. How can I combine the arrays that have the same room_id?
Upvotes: 0
Views: 71
Reputation: 700
I don't think the second example is actually the structure you'd like--there's no need to have the zero-indexed first dimension if you're just trying to store the dates for each room number, so that dimension just gets in the way. I think the best way to do this is to pass the existing subarray by reference to the function so that it can directly add elements onto the array. I rewrote your code (and also removed some redundancy/inefficiency), like the extra loop, to produce what I think you want:
$query = "SELECT res_id, room_id, guest_id, check_in_date, check_out_date FROM reservation ";
$result = mysqli_query($link, $query) or die (mysqli_error($link));
$rooms = array();
$array_date = array();
while ($row = mysqli_fetch_assoc($result)) {
$rooms[] = $row; // This is no longer used, but I'm assuming you want it for something else later
if (!array_key_exists($row['room_id'], $array_date)) {
$array_date[$row['room_id']] = array();
date_range($array_date[$row['room_id']], $row['room_id'], $row['check_in_date'], $row['check_out_date']);
} else {
date_range($array_date[$row['room_id']], $row['room_id'], $row['check_in_date'], $row['check_out_date']);
}
}
function date_range(&$currentDates, $room_id, $first, $last, $step = '+1 day', $output_format = 'Y-m-d' ) {
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$currentDates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
}
This should produce an array like this:
Array
(
[1] => Array // Room ID
(
[0] => 2015-04-08
[1] => 2015-04-09
[2] => 2015-04-10
[3] => 2015-04-11
[4] => 2015-04-12
[5] => 2015-04-13
)
[2] => Array // Room ID
(
[0] => 2015-04-08
[1] => 2015-04-09
[2] => 2015-04-10
[3] => 2015-04-11
[4] => 2015-04-12
[5] => 2015-04-13
)
)
So you can iterate through the dates available for each room by just doing:
foreach ($array_date as $roomNumber => $dates) {
foreach ($dates as $date) {
// Do something
}
}
This solution might allow for duplicate entries for dates, depending on how your table is set up. To avoid those duplicates, you could check to skip adding a date if the room is already reserved by replacing the contents of the while
loop in date_range()
with something like
if (!in_array(date($output_format, $current), $currentDates)) {
$currentDates[] = date($output_format, $current);
}
$current = strtotime($step, $current);
Hopefully this is the behavior you want. Let me know if not!
Upvotes: 1