3

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;
}
Phil Young
  • 1,334
  • 3
  • 21
  • 43

2 Answers2

1

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';
    }
}
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
0

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.

Community
  • 1
  • 1
J-Dizzle
  • 3,176
  • 6
  • 31
  • 49
  • Sorry, the print_r was just me trying to debug. I have it working on all of the days apart from the last :/ – Phil Young Jun 28 '14 at 01:00
  • makes more sense this way: change `foreach($week as $day)` to `foreach($day as $dayInfo)` , then i think you can change `$weeks` to `$week` and `$dates` to `$weeks` at the very top – J-Dizzle Jun 28 '14 at 01:05
  • Where is $weeks? I have $dates which is an array of 3 $weeks, which in turn is an array of 7 $days. – Phil Young Jun 28 '14 at 01:13
  • i thought it was at the top, but it is $week up there. Scratch that comment, it should be something like foreach ($weeks as $week) { foreach ($week as day) and then foreach ($day as $dayinfo). At least how you described the array it was an array with 4 weeks ($weeks has 4 $week arrays) , each week having 7 $day arrays ($week has 7 $day) and each $day has certain $dayinfo. – J-Dizzle Jun 28 '14 at 01:16
  • and other than that cleanup, if you made it a function where you pass in the $weeks array I would be much more able to work with it, because I don't really understand your goals. with Functions you give it input, you get output. You have this set up in a procedural way, which is poor style and looks very jumbled. How is the dates array created? include that code as well – J-Dizzle Jun 28 '14 at 01:20
  • Are you manually creating the array of dates, i.e. typing Mon 23rd Jun? etc – J-Dizzle Jun 28 '14 at 01:22
  • I've added the function this is from in the question, you'll see how it is declared there. – Phil Young Jun 28 '14 at 01:24
  • Hi, I couldn't get that to work, but the +7 days tidied up my code a bit, thanks :) The final Sunday in $dates[2][6] holds the $dates[2] array and it says recursion when I view a print_r() of it. The array input into the foreach($dates as $week) is fine, the error occurs when that foreach runs. – Phil Young Jun 28 '14 at 01:56
  • Thanks :) Jack found it above, it was a reference error. Thanks for the work :) – Phil Young Jun 28 '14 at 02:17