【问题标题】:Last item in foreach loop is the array it is traversingforeach 循环中的最后一项是它正在遍历的数组
【发布时间】:2014-08-19 04:30:17
【问题描述】:

我有一组包含日期、开始时间和结束时间的本周、下周和下周的日期。出于某种原因,当 foreach 循环到达最终日期时,它会输出最后一周的数组而不是最终日期。这是数组的开头:

$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"
                )
            ...

数组没有问题,因为我已经打印出来了。这是foreach循环(它是发生错误的嵌套foreach($week as $day)):

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;
}

谁能看出发生了什么?

编辑

我发现 $dates 没问题,问题是在上周运行 foreach($dates as $week) 循环时出现的。

重新编辑

这是 this 来自的函数。请不要判断,我继承了这个网站: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;
}

【问题讨论】:

  • 您在内部foreach 的HTML 末尾有一个额外的&lt;tr&gt;
  • 澄清一下,3 个表格中的每一个都将最后一行打印两次?还是只是最后一张桌子?
  • $dates[2][6] 中的最后一个星期日包含 $dates[2] 数组,当我查看它的 print_r() 时,它会显示 recursion。输入到 foreach($dates as $week) 的数组很好,当 foreach 运行时会发生错误。
  • 不影响报错。所以卡住了!
  • @PhilYoung 找到了,邪恶的引用:)

标签: php arrays foreach output


【解决方案1】:

TL;DR - 引用是邪恶的!

问题出在这里:

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

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

第一个循环结束后,上周仍然是一个参考,$dates[count($dates) - 1] 也是如此。在第二个循环中,$week 被依次分配给$dates 的每个元素。

当涉及到最后一个元素时,$week 被分配给它自己,从而创建了一个递归结构。

修复很简单:

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

或者:

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

【讨论】:

  • 这么简单的事情,我已经花了很长时间试图对它进行排序!谢谢:)
  • @PhilYoung 不客气;假设你在英国,你现在一定很累了:)
  • 是的,我是,凌晨 3 点 10 分!这个迟到的编码会议不应该运行这么长时间!哈哈。
【解决方案2】:

好的,

$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)

因此,如果您的目标只是打印“6 月 23 日星期一”,请尝试

print_r(day[0][0]);

另外,下次再提一下你是如何声明数组的,这会变得容易得多。我认为您的 $weeks 数组从外观上应该称为 $week 。

也似乎是无意的

编辑:我发现了错误

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

执行类似 date("D jS F", strtotime("monday next week + 7 day")。这将得到下周星期一 +7 天,也就是两周后的星期一。我不认为“”下周星期一”,strtotime(“下周星期一”)”是有效的语法。同样的错误可能在这里:

$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")))."'";

只是建议更好地生成日期,但对于您的商店或任何可能最方便的方式。 Create an array/collection/list of (Date,Value) in PHP 使用它来创建你的数组,如果你必须将它分成几个星期使用 array_chunk[$dates, 7]

重新编辑:

查看日期数组的末尾

  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"
    )

将其更改为下周 + 7 天,我认为它可能会有所帮助。

【讨论】:

  • 抱歉,print_r 只是我在调试。除了最后一天,我所有的日子都在工作:/
  • 这样更有意义:将 foreach($week as $day) 更改为 foreach($day as $dayInfo) ,然后我认为您可以将 $weeks 更改为 $week$dates 更改为 $weeks 在最顶部跨度>
  • $weeks 在哪里?我有 $dates,它是一个包含 3 个 $weeks 的数组,而它又是一个包含 7 个 $days 的数组。
  • 我以为它在顶部,但它在那里是 $week。从头开始,它应该类似于 foreach ($weeks as $week) { foreach ($week as day) 然后 foreach ($day as $dayinfo)。至少你是如何描述数组的,它是一个有 4 周的数组($weeks 有 4 个 $week 数组),每周有 7 个 $day 数组($week 有 7 个 $day),每个 $day 有一定的 $dayinfo。跨度>
  • 和除此之外的清理,如果你把它变成一个函数,你可以在 $weeks 数组中传递它,我会更能够使用它,因为我不太了解你的目标。用你给它输入的函数,你得到输出。你以一种程序化的方式进行设置,这种方式很糟糕,看起来很混乱。日期数组是如何创建的?也包括该代码
猜你喜欢
  • 2018-06-26
  • 2013-12-16
  • 1970-01-01
  • 2020-07-30
  • 2013-01-30
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多