2014-05-22 63 views
0

我還在學習PHP,並開始瞭解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代碼能夠處理這個問題,因此只有列出了「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 
) 

(‘遊戲’沒有的格式,所以它返回null - 這將是其中其它介質類型將列出‘平裝本’,‘CD’!等)

+0

因此,介質應該是脫離主要的foreach塊 –

+0

@RakeshSharma hoq這將有助於?! –

+0

如果介質的值發生變化,我只會在循環中輸出ul標籤。 – Kickstart

回答

1

與使用「的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> 
+0

我很欣賞這個答案,因爲它教會了我一些新的東西。然而,我有一個問題:這個結果是完美的,但kevinabelita提供的「foreach」方法也是如此。那麼,哪個「更好」?這兩種方法中的一種比另一種有優勢嗎? – Dion

+1

@Dion,思考它的方式不是'更好'或'最好'​​。它更多的是你現在有兩種解決問題的獨立方式:1)類似數量的代碼來實現2)容易理解和3)給出正確的結果。根據您嘗試解決的問題,您可以選擇適當的方法。有時「預讀」更易於使用,其他時間則是「foreach」。兩者都有其用途。當「嵌套」循環和輸入是單個流時,「預讀」通常更容易。 –

0

通過保存介質的前一個值並僅輸出th Ë標籤時,這個變化將使這樣的事情(未測試)

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

在一個相對簡單的列表這樣它可能是很容易做到的卡皮納思建議和組SQL中的物品,然後就爆炸出來在代碼中。

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; ?> 
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); 
?> 
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

+0

感謝您執行'$ value_from_db'數組。 –

+0

謝謝你的回答 - 它確實給出了結果,Ryan Vincent的回答也是如此,它使用了「預讀」技術。由於我仍然在學習PHP,「預讀」技術是一種更好的整體方法,而不是執行foreach循環嗎? – Dion