PHP foreach 在每个级别嵌套具有可变元素的列表?

标签 php mysql foreach

我仍在学习 PHP,并开始了解 foreach() 循环的工作原理。我被某件事困住了。

我正在使用 PHP 从 MySQL 数据库中绘图,我想列出有多少项共享相同的“topic_id”。使用初始数字,我尝试创建一个嵌套列表,用于标识每个项目可用于哪些不同的介质类型,以及每种介质中计数了多少个项目。

这是我正在使用的数据库查询:

SELECT 
  m.name AS medium, i.medium_id, f.name AS format, 
  SUM(
    CASE WHEN it.topic_id = '$topicId' AND i.id = it.item_id 
      THEN 1 
      ELSE 0 END
  ) AS sumFormat
FROM items AS i
LEFT JOIN item_topics AS it 
  ON i.id = it.item_id 
LEFT JOIN formats AS f 
  ON f.id = i.format_id 
LEFT JOIN media AS m 
  ON m.id = i.medium_id 
GROUP BY medium, format 
ORDER BY medium ASC

这给出了以下结果(我省略了 sumFormat=0 结果):

+--------------+-------------+--------------+-----------+
| medium       | medium_id   | format       | sumFormat |
+--------------+-------------+--------------+-----------+
| Games        |           1 | NULL         |         1 |
| Magazines    |           2 | Paperback    |        35 |
| Albums       |           3 | CD           |        25 |
| Albums       |           3 | Record       |         1 |
| Books        |           5 | Audiobook    |        38 |
| Books        |           5 | Diary        |         1 |
| Books        |           5 | Dictionary   |         4 |
| Books        |           5 | Ebook        |       421 |
| Books        |           5 | Hardback     |        76 |
| Books        |           5 | Paperback    |       574 |
| Comics       |           6 | Paperback    |         2 |
+--------------+-------------+--------------+-----------+

根据所查询的“$topicId”,结果会有所不同 - 在某些情况下,给定媒体或格式中可能不存在任何项目。我希望 PHP 代码能够处理这个问题,因此只会列出“topic_id”存在的媒体类型和格式。

在我的 PHP 代码中,我将其组合在一起,如下所示:

<ul id="formats">
<?php foreach ($topicFormats as $topicFormat): ?>
    <?php if ($topicFormat['medium'] && $topicFormat['sumFormat']): ?>
        <li><?= $topicFormat['medium'] ?></li>
            <?php if ($topicFormat['sumFormat']): ?>
                <ul>
                <li><?= $topicFormat['sumFormat'] ?>
                    <?php if (!$topicFormat['format']): ?>
                        Games
                    <?php else: ?><?= $topicFormat['format'] ?>
                        <?php endif; ?>
                </li>
                </ul>
            <?php endif; ?>
    <?php endif; ?>
<?php endforeach; ?>

最终的 HTML 如下所示:

    1178 Items
    • Games
        • 1 Games
    • Magazines
        • 35 Paperback
    • Albums
        • 1 Record
    • Albums
        • 25 CD
    • Books
        • 38 Audiobook
    • Books
        • 1 Diary
    • Books
        • 4 Dictionary
    • Books
        • 421 Ebook
    • Books
        • 76 Hardback
    • Books
        • 574 Paperback
    • Comics
        • 2 Paperback

但是我想要以下结果:

    1178 Items
    • Games
        • 1 Games
    • Magazines
        • 35 Paperback
    • Albums
        • 1 Record
        • 25 CD
    • Books
        • 38 Audiobook
        • 1 Diary
        • 4 Dictionary
        • 421 Ebook
        • 76 Hardback
        • 574 Paperback
    • Comics
        • 2 Paperback

我在 StackOverFlow 上检查过这个问题,但没有找到任何解决方案。 任何帮助将不胜感激!

编辑:我还没有机会尝试你的任何建议,但为了回答Kapilgopinath,这里是结果数组(我认为这个就是你所要求的 - 我以前从未检索过结果数组!):

Array 
(
[0] => Games
[medium] => Games
[1] => 1 
[medium_id] => 1 
[2] => 
[format] => 
[3] => 1 
[sumFormat] => 1 
) 

(“Games”没有格式,因此它返回 null - 这将是其他媒体类型列出“Paperback”、“CD”等的位置)

最佳答案

使用“foreach”循环的问题是,直到循环结束才完成下一次读取,当您有一个“嵌套循环”时,这已经太晚了。使用“预读”技术会更容易,尽管代码不少。优点是您不需要 if 测试来确定如何处理当前条目。因此你需要一个迭代器,那么它只是嵌套循环。在处理当前记录后立即读取下一条记录。

<?php
    $values_from_db = array( array( 'medium' => 'Games', 'format' => 'Games', 'sumFor' => 1, ), array( 'medium' => 'Magazines', 'format' => 'Paperback', 'sumFor' => 35, ), array( 'medium' => 'Albums', 'format' => 'CD', 'sumFor' => 25, ), array( 'medium' => 'Albums', 'format' => 'Record', 'sumFor' => 1, ), array( 'medium' => 'Books', 'format' => 'Audiobook', 'sumFor' => 38, ), array( 'medium' => 'Books', 'format' => 'Diary', 'sumFor' => 1, ), array( 'medium' => 'Books', 'format' => 'Dictionary', 'sumFor' => 4, ), array( 'medium' => 'Books', 'format' => 'Ebook', 'sumFor' => 421, ), array( 'medium' => 'Books', 'format' => 'Hardback', 'sumFor' => 76, ), array( 'medium' => 'Books', 'format' => 'Paperback', 'sumFor' => 574, ), array( 'medium' => 'Comics', 'format' => 'Paperback', 'sumFor' => 2, ), );

    $iterSumFor = new ArrayIterator($values_from_db);
    $curEntry = $iterSumFor->current(); // read ahead -- always a current record to process
?>
<ul>
<?php while ($iterSumFor->valid()): ?>
    <?php $curMedium = $curEntry['medium']; ?>
    <li><?= $curMedium ?></li>
    <ul>
        <?php while ($iterSumFor->valid() && $curEntry['medium'] == $curMedium): ?>
            <li><?= $curEntry['sumFor'], '&nbsp;', $curEntry['format'] ?></li>
            <?php $iterSumFor->next(); ?>
            <?php $curEntry = $iterSumFor->current(); ?>
        <?php endwhile; ?>
    </ul>
<?php endwhile ?>
</ul>

关于PHP foreach 在每个级别嵌套具有可变元素的列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23801722/

相关文章:

php - 在 MySQL 中,如何只选择给定列具有特定值的行?

mysql - 我的查询导致 mysqlid CPU 使用率达到 99%,我想简化查询

带有 map 和倍数集的 Java 8 Stream

java - 对于使用二维数组的每个循环

c++ - 为什么这个仿函数的析构函数被调用两次?

php - validate() 返回 false 但 getErrors() 返回一个空数组 - Yii

java - 使用 php 和 android 将小尺寸图像上传到服务器

mysql - SELECT WITH CALL PROCEDURE MySQL

php - 使用 PHP 更新 MySQL 字段的问题

javascript - AngularJS 在 Wordpress 插件中工作吗