当前位置: 首页 > 知识库问答 >
问题:

PHP Foreach循环使用一个条目两次

姜奇
2023-03-14

我只是用PHP和PDO在MySQL数据库中工作进行了一些实验,我有点困惑为什么在得到结果后,将它们正确地存储在多维数组中,并循环通过它们,它会两次输出其中一个数组数据。

基本上,以下是获取数据的查询:

SELECT b.Price, b.ImgURL, m.Name, f.ID, f.Family, f.URL FROM Products AS b INNER JOIN Manufacturers AS m ON m.ID = b.Manufacturer INNER JOIN FamilyLookUp AS l ON l.Product = b.ID INNER JOIN Families AS f ON f.ID = l.Family GROUP BY f.ID ORDER BY b.Price ASC

我希望与此得到1行返回每个家庭,它在PHPMyAdmin查询和print_r()结果时都能正常工作。

然后我存储在:

$families[] = array('ID' => $f['ID'], 'Manufacturer' => $f['Name'], 'Family' => $f['Family'], 'URL' => $f['URL'], 'IMG' => $f['ImgURL'], 'Price' => $f['Price'], 'ScentCount' => 0);

在执行print_r()时,以及在foreach循环中回显每个条目的ID时,它也可以正常工作,返回1234567(所有7个族ID)

然后我运行另一个查询:

try{
$sqlCmd = "SELECT COUNT(*) FROM FamilyLookUp WHERE Family=:fID";
$s = $pdo->prepare($sqlCmd);
foreach($families as &$fam){
$s->bindValue(':fID', $fam['ID']);
$s->execute();
$fam['ScentCount'] = $s->fetchColumn();
}
}

这也获得了正确的计数,并正确地将它们存储在数组中,用于每个家庭中的项目数量。到目前为止一切都很好。

当我:

foreach($families as $fam):
        ?>

        <div class="product-listing">
        <?php echo $fam['ID']; ?>
            <div class="product-listing-image">
                <a href="<?php echo $fam['URL']; ?>"><img alt="" src="<?php echo $fam['IMG']; ?>"></a>
            </div>
            <div class="product-listing-details">

                <a href="<?php echo $fam['URL']; ?>"><h3><?php echo strtoupper($fam['Manufacturer']); if($fam['Family'] != ""){ echo strtoupper(' - ' . $fam['Family']);} ?></h3></a>
                <?php if($fam['ScentCount'] == 1): ?>
                <span class="product-scent-count"><?php echo $fam['ScentCount']; ?> Scent</span>
                <span class="product-price-value">£<?php echo $fam['Price']/100; ?></span>
                <?php elseif($fam['ScentCount']>1): ?>
                <span class="product-scent-count"><?php echo $fam['ScentCount']; ?> Scents</span>
                <span class="product-price-value">From £<?php echo $fam['Price']/100; ?></span>
                <?php endif;?>
            </div>
        </div>

        <?php
            endforeach;
        ?>

执行此操作后,它会正确输出前6个数据族,但由于某些原因,它会输出第6个数据族的副本,而不是实际的第7个数据族。当在foreach循环开始之前打印行中的所有数据时,它返回所有正确的数据,但在foreach循环中,在原来正确的第7个数组的位置上有一个重复数组。

任何建议都会很棒。

编辑Kohloth的答案(打印后紧接着foreach vardump):

Array
(
    [0] => Array
        (
            [ID] => 1
        )

    [1] => Array
        (
            [ID] => 7
        )

    [2] => Array
        (
            [ID] => 2
        )

    [3] => Array
        (
            [ID] => 3
        )

    [4] => Array
        (
            [ID] => 4
        )

    [5] => Array
        (
            [ID] => 6
        )

    [6] => Array
        (
            [ID] => 5
        )

)
            array(7) {
  ["ID"]=>
  string(1) "1"
}

    array(7) {
  ["ID"]=>
  string(1) "7"
}

    array(7) {
  ["ID"]=>
  string(1) "2"
}

    array(7) {
  ["ID"]=>
  string(1) "3"
}

    array(7) {
  ["ID"]=>
  string(1) "4"
}

    array(7) {
  ["ID"]=>
  string(1) "6"
}

    array(7) {
  ["ID"]=>
  string(1) "6"
}

共有2个答案

施永宁
2023-03-14

不管它有什么价值,第二双眼睛看不到代码的HTML输出部分有什么问题。这并没有改变你正在迭代的数组的结构,所以在我看来,也许你的诊断是不对的?值得对最后一个foreach循环进行注释,并将其替换为:

<?php foreach($families as $fam): ?>
    <?php var_dump($fam);?> 
<?php endforeach; ?>

只需在输入HTML重载foreach块之前再次检查$families数组是否正确。

编辑:我在运行视图代码之前直接使用了一个显式数组声明,它不会复制上一个结果。当您将其直接放在视图代码之前时会发生什么?

$families = [
    [
        'ID' => 1,
        'Manufacturer' => 'man1',
        'Family' => 'fam1',
        'URL' => 'url1',
        'IMG' => 'img1',
        'Price' => 'price1',
        'ScentCount' => 1
    ],
    [
        'ID' => 2,
        'Manufacturer' => 'man2',
        'Family' => 'fam2',
        'URL' => 'url2',
        'IMG' => 'img2',
        'Price' => 'price2',
        'ScentCount' => 2
    ],
    [
        'ID' => 3,
        'Manufacturer' => 'man3',
        'Family' => 'fam3',
        'URL' => 'url3',
        'IMG' => 'img3',
        'Price' => 'price3',
        'ScentCount' => 3
    ],

];

?
司立果
2023-03-14

这就是正在发生的事情:

在该循环的最后一次迭代中:

foreach($families as &$fam){
    $s->bindValue(':fID', $fam['ID']);
    $s->execute();
    $fam['ScentCount'] = $s->fetchColumn();
}

... $fam指的是$families数组的最后一个元素。

然后,当下一个循环开始时:

foreach($families as $fam){

...$fam指向的内存位置不会改变,它仍然锁定在$家庭数组的最后一个元素上。因此,在第一次迭代中,第一个元素的内容被复制到$fam中,即在最后一个条目中,然后在第二次迭代中,第二个值被覆盖在那里,依此类推。当最后一次迭代开始时,最后一个元素包含一个但最后一个值,这个值被...本身覆盖,这也是一个但最后一个值。

这个错误报告提出了同样的问题,给出的答案是这是预期的行为。在回答一个重复的错误报告时,这是非常中肯的:

目前的实施是一致的。当然,这不是很有用,但在这里随意打断引用是不一致的
PHP没有块作用域,打破引用会在这里引入一个特例块作用域。

这个博客用漂亮的插图解释了同样的行为。

解决方案是在第二个循环中使用另一个新变量,如下所示:

foreach($families as $fam2){

或者,对于可能使用$fam的任何其他代码来说,更安全的方法是在第二个循环之前unset($fam),如下所示:

unset($fam);
foreach($families as $fam){

这是有效的,因为在Foreach循环的开始,变量是从头开始重新创建的,因此指向它自己的新内存位置。

foreach上的文档中有关于此行为的警告,并建议unset

警告

$value的引用和最后一个数组元素即使在foreach循环之后仍然保留。建议通过unset()将其销毁。

所有这些都很尴尬,当你阅读相关“bug”报告的回复时,很明显,你不是唯一一个遇到这种意外副作用的人。因此,我想强调这一点:

几乎从未真正需要使用此

您的代码可以在没有

foreach($families as $i => $fam){
    $s->bindValue(':fID', $fam);
    $s->execute();
    // use the index to put the value in place in the array:
    $families[$i]['ScentCount'] = $s->fetchColumn();
}

请注意,它也不会损害代码的可读性。

 类似资料:
  • 2.它指向将要插入下一个元素的地方 在这两种情况下,如果我们没有浪费数组的至少一个条目,或者如果我们没有保持计数器计数,我们就无法区分full和empty队列

  • 问题内容: 在python中,我该怎么做: 问题答案: 其他答案仅适用于序列。 对于任何迭代,请跳过第一项: 如果要跳过最后一个,可以执行以下操作:

  • 我有两个类型为< code>std::vector的向量a和b <代码>矢量a - 我想用这两个向量形成循环 下面的代码是我创建向量v1以形成循环“c”,将值推入其中,执行操作并返回向量或循环c。 x=a.at(i),y=b.at(i) 例如:x=a.at(1),y=b.at(1) 我想知道如何编写这个循环来执行上述操作。

  • 无法找到这个问题的答案。我有一个mysqli循环语句。在这个循环中,我想运行另一个查询。我不能同时编写这两个sql。可能吗?我想,因为我使用stmt并设置它来准备语句。所以我添加了另一个变量stmt2。单独运行它们是可行的,但像我写的那样运行它会给我“mysqli致命错误:对非对象调用成员函数bind_param()” 伪代码: 答案是: 我真傻,我不知道我必须有两个mysqli连接。所以解决方案

  • 我在汇编语言中遇到了循环问题。 当我们想要使用计数器寄存器在嵌套循环中循环时,我们首先要做的是将计数器寄存器的值移动到外部循环的堆栈中,然后在我们完成内部循环时取回它,这样我们就能够使用一个计数器寄存器在每个循环中循环不同的迭代次数。 但是嵌套循环中的嵌套循环呢? 我想打印一个由字符< code>S组成的金字塔。我得到的是, 我真正想要的是, 这是我的程序代码 为了实现我想要的,我需要在嵌套循环中

  • 我正在努力解决这个问题。工作内容:我想打印表中的所有3行(将附上示例),并在EID列中显示值。 我想测试EID1(第一行)的值是否以8开头。(完成) 我想测试CID1(第一行)的值是否以“M”开头。(完成) 现在我想循环整个表,并检查每一行的以下条件,例如:(Done) 如果EID1= 我得到以下错误:无法调用“String.startsWith(String)”,因为java的返回值。util。