foreach循环中的最后一项是它遍历的数组

I have an array of this weeks, next weeks and the week after's dates holding the date, an opening time and a closing time. For some reason, when the foreach loop reaches the final date, it outputs the array of the final week instead of the final date. Here is the start of the array:

$dates = Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => "Mon 23rd June"
                    [1] => "9:00am"
                    [2] => "7:00pm"
                )

            [1] => Array
                (
                    [0] => "Tue 24th June"
                    [1] => "9:00am"
                    [2] => "7:00pm"
                )
            ...
    [1] => Array
        (

            [0] => Array
                (
                    [0] => "Mon 30th June"
                    [1] => "9:00am"
                    [2] => "7:00pm"
                )

            [1] => Array
                (
                    [0] => "Tue 1st July"
                    [1] => "9:00am"
                    [2] => "7:00pm"
                )
            ...

There is no issue with the array, as I have printed it out. Here is the foreach loop (it is the nested foreach ($week as $day) where the error occurs):

foreach($dates as $week)
{ 
    if($i == 2)
    {
        $html .= '<table cellpadding="5" cellspacing="2" border="0" class="kc_ot_openingTable last">';
    }
    else
    {
        $html .= '<table cellpadding="5" cellspacing="2" border="0" class="kc_ot_openingTable">';
    }
    $html.= '<tr class="kc_ot_weekCommence">
        <td colspan="3">Week Commencing '.$week[0][0].'</td>
    </tr>
    <tr class="kc_ot_openingTableTitle">
        <td class="day">Day</td>
        <td class="open">Open</td>
        <td class="closed">Closed</td>
    </tr>';

    foreach($week as $day)
    {
        $html .= '<tr>
        <td>'.$day[0].'</td>
        <td class="open">'.$day[1].'</td>
        <td class="closed">'.$day[2].'</td>
    </tr>
    <tr>';
    }
    $html .= '</table>';
    ++$i;
}

Can anyone spot what is going on?

Edit

I have found out that $dates is fine, the problem occurs when the foreach($dates as $week) loop runs on the last week.

Re Edit

Here is the function that this comes from. Please don't judge, I inherited this site :P

function getOpeningHours() {

date_default_timezone_set('Europe/London');
$dates = array(
    array(
        array(
            date("D jS F", strtotime("monday this week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("tuesday this week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("wednesday this week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("thursday this week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("friday this week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("saturday this week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("sunday this week")),
            "9:00am",
            "7:00pm"
        ),
    ),
    array(
        array(
            date("D jS F", strtotime("monday next week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("tuesday next week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("wednesday next week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("thursday next week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("friday next week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("saturday next week")),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("sunday next week")),
            "9:00am",
            "7:00pm"
        ),
    ),
    array(
        array(
            date("D jS F", strtotime("monday next week", strtotime("monday next week"))),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("tuesday next week", strtotime("tuesday next week"))),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("wednesday next week", strtotime("wednesday next week"))),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("thursday next week", strtotime("thursday next week"))),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("friday next week", strtotime("friday next week"))),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("saturday next week", strtotime("saturday next week"))),
            "9:00am",
            "7:00pm"
        ),
        array(
            date("D jS F", strtotime("sunday this week", strtotime("sunday next week"))),
            "9:00am",
            "7:00pm"
        )
    ),
);

$sql[0] = "SELECT * FROM `tbl_opening_exceptions` WHERE `exception_date`  >= '".date("Y-m-d", strtotime("monday this week"))."' AND `exception_date` <= '".date("Y-m-d", strtotime("sunday this week"))."'";
$sql[1] = "SELECT * FROM `tbl_opening_exceptions` WHERE `exception_date`  >= '".date("Y-m-d", strtotime("monday next week"))."' AND `exception_date` <= '".date("Y-m-d", strtotime("sunday next week"))."'";
$sql[2] = "SELECT * FROM `tbl_opening_exceptions` WHERE `exception_date`  >= '".date("Y-m-d", strtotime("monday next week", strtotime("monday next week")))."' AND `exception_date` <= '".date("Y-m-d", strtotime("sunday next week", strtotime("sunday next week")))."'";
$i=0;
foreach($sql as $string)
{
    $result = mysql_query($string) or die(mysql_error());
    $r = mysql_fetch_array($result);

    foreach($dates[$i] as &$week)
    {
        if($week[0] == date("D jS F", strtotime($r["exception_date"])))
        {
            $week[1] =  date("g:ia", strtotime($r["exception_opening"]));
            $week[2] = date("g:ia", strtotime($r["exception_closing"]));
        }
    }
    ++$i;
}
$html = "";
$i = 0;
//print_r($dates);
foreach($dates as $week)
{ 
print_r($week);
    if($i == 2)
    {
        $html .= '<table cellpadding="5" cellspacing="2" border="0" class="kc_ot_openingTable last">';
    }
    else
    {
        $html .= '<table cellpadding="5" cellspacing="2" border="0" class="kc_ot_openingTable">';
    }
    $html.= '<tr class="kc_ot_weekCommence">
        <td colspan="3">Week Commencing '.$week[0][0].'</td>
    </tr>
    <tr class="kc_ot_openingTableTitle">
        <td class="day">Day</td>
        <td class="open">Open</td>
        <td class="closed">Closed</td>
    </tr>';

    foreach($week as $day)
    {
        $html .= '<tr>
        <td>'.$day[0].'</td>
        <td class="open">'.$day[1].'</td>
        <td class="closed">'.$day[2].'</td>
        </tr>';
    }
    $html .= '</table>';
    ++$i;
}
return $html;
}

TL;DR - References are evil!

The problem lies here:

foreach ($dates[$i] as &$week) {
    // updates based on database values
}

foreach ($dates as $week) {
    // generate html from week data
}

After the first loop finishes, the last week is still a reference and so is $dates[count($dates) - 1]. Inside the second loop, $week gets assigned each element of $dates in turn.

When it comes to the last element, $week gets assigned to itself and thus a recursive structure is created.

The fix is simple:

foreach ($dates[$i] as &$week) {
    // updates based on database values
}
unset($week); // remove the reference

Alternatively:

foreach ($dates[$i] as $week) {
    // updates based on database values
    if (<some condition>) {
        $dates[$i][1] = 'foo';
        $dates[$i][2] = 'bar';
    }
}

Okay,

$weeks = array(
array(
array("Mon 23rd June", "9:00 AM", "7:00 PM"),
array("Tue 24th June", "9:00 AM", "7:00 PM"),
array("Wed 25th June", "9:00 AM", "7:00 PM") //etc
),
array() // another week 
)
$dates = array($weeks)

So if your goal is to just print "Mon 23rd June", try

print_r(day[0][0]);

Also, next time mention how you are declaring the array, and this becomes a lot easier. I think your $weeks array should be called $week from the looks of it. Also the < /tr > < tr > seems unintentional

edit: I found the error

array(
        date("D jS F", strtotime("monday next week", strtotime("monday next week"))),
        "9:00am",
        "7:00pm"
    ),

Do something like date("D jS F", strtotime("monday next week + 7 day"). This would get monday next week +7 days, aka monday two weeks from now. I don't think ""monday next week", strtotime("monday next week")" is valid syntax. The same error may be here:

$sql[2] = "SELECT * FROM `tbl_opening_exceptions` WHERE `exception_date`  >= '".date("Y-m-d", strtotime("monday next week", strtotime("monday next week")))."' AND `exception_date` <= '".date("Y-m-d", strtotime("sunday next week", strtotime("sunday next week")))."'";

Just a suggestion to have the dates generated better, but for your store or whatever that way might be the most convienient. Create an array/collection/list of (Date,Value) in PHP Use this to create your array, and if you have to split it into weeks use array_chunk[$dates, 7]

Re Edit:

Look at the very end of that array of dates

  array(
        date("D jS F", strtotime("saturday next week", strtotime("saturday next week"))),
        "9:00am",
        "7:00pm"
    ),
    array(
        date("D jS F", strtotime("**sunday *this* week**", strtotime("sunday next week"))),
        "9:00am",
        "7:00pm"
    )

Change that to next week + 7 day and I think it might do some good.