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

时间:2014-05-22 08:36:00

标签: php mysql foreach

我还在学习PHP,并开始了解foreach()循环的工作。我被困在某事上。

我正在使用来自MySQL数据库的PHP绘图,我想列出共享相同数量的项目" 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代码能够处理这个问题,所以只有#34; 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 
) 

(&#34;游戏&#34;没有格式,所以它返回null - 这将是其他媒体类型列出的地方&#34;平装&#34;,&#34; CD&# 34;等。)

5 个答案:

答案 0 :(得分:1)

首先,您需要先对查询的主要结果进行分组。从那时起,您可以循环它们并构建列表。这是一般性的想法,请考虑这个例子:

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

// group them first
$formatted_array = array();
foreach($values_from_db as $key => $value) {
    $formatted_array[$value['medium']][] = $value;
}

$list = '<ul>';
foreach($formatted_array as $key => $value) {
    $list .= "<li>$key</li>";
    if(is_array($value)) {
        $list .= "<ul>";
        foreach($value as $index => $element) {
            $list .= "<li>$element[sumFor] $element[format]</li>";
        }
        $list .= "</ul>";
    }
}
$list .= '</ul>';

print_r($list);

Sample Fiddle

答案 1 :(得分:1)

使用&#39; foreach&#39;循环是在循环结束之前没有完成下一次读取,这已经太晚了,当你有一个“嵌套循环”时。就在这里。使用&#39;提前阅读&#39;可以更容易,但不是更少的代码。技术。优点是您不需要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>

答案 2 :(得分:0)

通过保存介质的先前值并仅在此更改时仅输出标记(未经测试)来执行此操作

<ul id="formats">
<?php 
$prev_medium = '';
foreach ($topicFormats as $topicFormat)
{
    if ($topicFormat['medium'] && $topicFormat['sumFormat'])
    {
        if ($prev_medium != $topicFormat['medium'])
        {
            if ($prev_medium != '')
            {
                echo '</ul>';
                echo '</li>';
            }
            echo '<li>'.$topicFormat['medium'].'</li>';
            echo '<ul>';
            $prev_medium = $topicFormat['medium'];
        }
        if ($topicFormat['sumFormat'])
        {
            echo '<li>'.$topicFormat['sumFormat'];
            echo (($topicFormat['format']) ? $topicFormat['format'] : 'Games' );
            echo '</li>';
        }
    }
}
if ($prev_medium != '')
{
    echo '</ul>';
    echo '</li>';
}
?>
</ul>

在这样一个相对简单的列表中,可能很容易做到,因为Kapil gopinath建议并在SQL中对项目进行分组,然后在代码中将它们分解出来。

答案 3 :(得分:0)

$i =0; $a = array();
<ul id="formats">
<?php foreach ($topicFormats as $topicFormat): ?>
    <?php if ($topicFormat['medium'] && $topicFormat['sumFormat']): ?>
        <li><?php  if(!in_array($topicFormat['medium'], $a)) {
                      $a[$topicFormat['medium']]= $topicFormat['medium'];
                      echo $a[$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; ?>

答案 4 :(得分:0)

try this.    


<?php foreach ($topicFormats as $topicFormat): ?>
        <?php 
        $medium = $topicFormat['medium'];
        $format = $topicFormat['format']          
        $format[$medium][] = $topicFormat['sumFormat'].' '. $format ? $format : 'Games'; 
        <?php endforeach;        
        echo '<pre>';
        print_r($arr);
?>