PHP foreach在每一层嵌套具有可变元素的列表?
我还在学习PHP,并且已经开始了解foreach()循环的工作原理。我被什么东西卡住了 我正在使用一个MySQL数据库中的PHP绘图,我想列出有多少项共享相同的“topic_id”。对于初始数字,我尝试创建一个嵌套列表,该列表标识每个项目在哪些不同的介质类型中可用,以及每个介质中有多少个项目 这是我正在使用的数据库查询:PHP foreach在每一层嵌套具有可变元素的列表?,php,mysql,foreach,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.topi
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结果):
根据所查询的“$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; ?>
但是,我希望得到以下结果:
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时,这里是结果数组(我想这就是你想要的-我以前从未检索过结果数组!):
(“游戏”没有格式,因此它返回空值-这将是其他媒体类型列出“平装本”、“CD”等的地方。)通过保存媒体的上一个值来执行此操作,并且仅当此更改给出类似的内容时才输出标签(未测试)
在这样一个相对简单的列表中,可能很容易按照Kapil gopinath的建议进行操作,并在SQL中对项目进行分组,然后在代码中分解出来。试试看
$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; ?>
$i=0$a=数组();
-
游戏
试试这个。
首先,您需要首先对查询的主要结果进行分组。从那时起,您可以循环它们并构建列表。这里是总体思路,考虑这个例子:
<?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'], ' ', $curEntry['format'] ?></li>
<?php $iterSumFor->next(); ?>
<?php $curEntry = $iterSumFor->current(); ?>
<?php endwhile; ?>
</ul>
<?php endwhile ?>
</ul>
$values\u from\u db=array(array('medium'=>'Games','format'=>'Games','sumFor'=>1,),array('medium'=>'杂志','format'=>'平装本','sumFor'=>35,),array('medium'=>'相册','format'=>'CD','sumFor'=>25,),array('medium'=>'相册','format'=>'唱片','sumFor'=>1,),array('medium'=>'Books','format'=>'Audiobook','sumFor'=>38,),数组('medium'=>'Books','format'=>1,),数组('medium'=>'Books','format'=>'Dictionary','sumFor'=>4,),数组('medium'=>'Books','format'=>'Ebook','sumFor'=>421,),数组('medium'=>'Books','format'=>精装本','sumFor'=>76,),数组('medium'=>'Books','format'=>'平装本','sumFor'=>574,),数组('medium'=>'漫画','format'=>'平装本','sumFor'=>2,);
//先把他们分组
$formatted_array=array();
foreach($value\u作为$key=>$value来自\u数据库){
$formatted_数组[$value['medium']][]=$value;
}
$list=“”;
foreach($key=>$value格式的数组){
$list.=“- $key
”;
if(是_数组($value)){
$list.=“”;
foreach($index=>$element的值){
$list.=“- $element[sumFor]$element[format]
”;
}
$list.=“
”;
}
}
$list.='
';
打印(列表);
使用“foreach”循环的问题是,下一次读取要到循环结束时才能完成,这太晚了,因为此时您有了此处的“嵌套循环”。使用“预读”技术可能更容易,但代码不会更少。优点是您不需要if测试来确定如何处理当前条目。因此你需要一个迭代器,然后它就是嵌套的循环。读取下一条记录时,在当前记录被处理后立即读取
因此介质应位于主foreach之外block@RakeshSharmahoq这会有帮助吗?!我只会在介质值发生变化的情况下在循环中输出ul标记。这可以通过对结果数组进行分组来实现。你能粘贴结果$topicFormats数组吗。@Kapilgopinath我已经添加了结果数组(希望我做得对!)我真的很感激这个答案,因为它教会了我一些全新的东西。然而,我有一个问题:这给出了完美的结果,但kevinabelita提供的“foreach”方法也是如此。那么,哪一个“更好”?这两种方法中的一种比另一种有优势吗?@Dion,思考这两种方法的方式不是“更好”或“最好”。更重要的是,你现在有两种不同的方法来解决问题:1)实现的代码量相似2)易于理解3)给出正确的结果。根据您试图解决的问题选择适当的方法。有时“预读”更容易使用,而有时“预读”。两者都有各自的用途当存在“嵌套”循环且输入为单个流时,“预读”通常更容易。感谢您的回答-它确实给出了结果,Ryan Vincent的回答也给出了结果,使用了“预读”技术。既然我还在学习PHP,“预读”技术是一种更好的整体方法,而不是foreach循环吗?
Array
(
[0] => Games
[medium] => Games
[1] => 1
[medium_id] => 1
[2] =>
[format] =>
[3] => 1
[sumFormat] => 1
)
<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>
$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; ?>
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);
?>
$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);
<?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'], ' ', $curEntry['format'] ?></li>
<?php $iterSumFor->next(); ?>
<?php $curEntry = $iterSumFor->current(); ?>
<?php endwhile; ?>
</ul>
<?php endwhile ?>
</ul>