在嵌套循环中使用数组耗尽内存

Memory exhausted using an array in a nested loop

这是我遇到的错误。

Fatal Error: Allowed memory size exhausted.

我正在获取包含日期 from 和日期 till 的数组。我正在尝试获取介于两者之间的所有日期并将它们添加到新数组中。显然嵌套循环和多数组很累。

我需要一种不那么费力的方法来获取所有日期。

这是我的代码:

$query = "SELECT *
          FROM reservate
          ORDER BY from";
$result = $connect->query($query);

$reservations = array();
if ($result->num_rows > 0) {
    while($row = $result->fetch_assoc()) {
        $reservations[] = $row;
    }
}

$connect->close();

//AVAILABILITY CHECK
$nonAvailable = array();
foreach($reservations as $reservation){
    $from = $reservation['from'];
    $till = $reservation['till'];

    while($from <= $till){
        $nonAvailable[] = $from;
        $from = date('Y-m-d', strtotime("+1 days"));
    }
}

看起来你做了一个无限循环1.

// if $till is in the future, this is an infinite loop
while($from <= $till){
    // appending the same value of $from on each iteration
    $nonAvailable[] = $from;
    // as $from never changes value
    $from = date('Y-m-d', strtotime("+1 days"));
}

1 天添加到 $from

的当前值
while ($from <= $till){
     $nonAvailable[] = $from;
     // add 1 day to $from
     $from = date('Y-m-d', strtotime($from, "+1 days"));
}

还有一些可以改进的地方:

  • 在以下示例中,整个 table 未复制到 reservation 数组,我们只检索我们需要的列 来自 table。
  • 比较 integers 而不是 strings
  • 手动将 1 天添加到 $from 而不是依靠 strtotime 来完成。
$query = "SELECT from, till
          FROM reservate
          ORDER BY from";
$result = $connect->query($query);

$nonAvailable = array();

if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
        $from = strtotime($row['from']);
        $till = strtotime($row['till']);

        while ($from <= $till) {
            $nonAvailable[] = date('Y-m-d', $from);
            $from += 60*60*24;
        }
    }
}

$connect->close();

很可能可以使该算法更加高效。例如,您是否需要一份包含每天保留内容的详尽清单?如果不是,那么只需开始日期和结束日期就足够了。


1 如果有足够的时间和内存,循环将退出,因为 strtotime("+1 days") 最终会 return 一个大于 $till 的值。

另一种方法,只使用一个查询。

这需要您的预订 table 并将其与几个获取数字范围的子查询交叉连接。每人得到0到9的数字,一个为个位,一个为十位。将它们组合在一起会给你数字 0 到 99(所以 99 天范围)。

WHERE 子句只检查开始日期 (van) 加上天数(从 0 到 99)小于或等于结束日期 (tot)。因此,一个房间(我假设是多个房间,或者其他一些被预订出去的项目)在每个预订日期都会被淘汰:-

SELECT room, DATE_ADD(van, INTERVAL (tens.i * 10 + units.i) DAY) AS non_available
FROM reservate
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
WHERE DATE_ADD(van, INTERVAL (tens.i * 10 + units.i) DAY) <= tot
ORDER BY room, non_available

SQL fiddle 示例:-

http://www.sqlfiddle.com/#!9/83054/1

您可以使用 table 个整数来代替 2 个子查询。