Louie Cheung
Louie Cheung

Reputation: 77

Combine sub-arrays of an array that have the same key

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

Answers (1)

Chris Brendel
Chris Brendel

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

Related Questions