Php 如何从递归查询构建嵌套div的精确形式?
我有一个有点复杂的递归postgresql查询,它引入了如下内容(为了解决这个问题,我简化了它):Php 如何从递归查询构建嵌套div的精确形式?,php,html,Php,Html,我有一个有点复杂的递归postgresql查询,它引入了如下内容(为了解决这个问题,我简化了它): id depth path has_children 1 1 1 true 2 2 1.2 true 3 3 1.2.3 true 4 4 1.2.3.4 true 5 5 1.2.3.4.5 false 6 1 6
id depth path has_children
1 1 1 true
2 2 1.2 true
3 3 1.2.3 true
4 4 1.2.3.4 true
5 5 1.2.3.4.5 false
6 1 6 true
7 2 6.7 true
8 3 6.7.8 false
9 1 9 false
10 1 10 true
11 2 10.11 false
这是作为获取的结果(对于那些想知道为什么我将一些数组解析为对象的人来说,这是因为行作为对象获取,而我只是复制结果):
我想将结果转换为(使用给定的类名):
一,
1.2
1.2.3
1.2.3.4
1.2.3.4.5
六,
6.7
6.7.8
九,
十,
10.11
然而,在看了太多涉及ul
和li
的例子后,我感到困惑不解。由于嵌套的ul
s和li
s与嵌套的div
s不同,因此调整此类示例以供我使用失败
我想要一个干净的解决方案,使用
foreach
(最好)或while
循环(不需要递归函数)。我也不希望将结果重新创建为多维数组。您需要将db数据提取到一个数组中,该数组可以循环使用深度和子数组,并将数据传递到一个新的多维数组,如下所示:
array(
'1' => array(
'1.2' => array(
'1.2.3' => array(
'1.2.3.4' => array('1.2.3.4.5')
)
)
),
'6' => array(
'6.7' => array('6.7.8')
)
);
然后,您可以循环它,并使用foreach将每个数组作为div进行回显
假设您以array('row'=>array('key'=>'value','etc'=>'more'))的形式发布了从示例表中获取的数据。对于每一行,您需要检查['has_children']
值。如果它的计算结果为true,那么应该将深度作为一个整数,并使用for循环,例如for($i=0;$i$path){
if(is_数组($path)){
//检查是否是第一个。
$class=(strpos('.',$name))?'baz':'bar';
回显“\n\t”;
echo“\n\t{$name}\n\n\n”;
显示($path);
回声“;
}否则{
回显“\n\t”;
echo“\n\t{$path}\n”;
回声“;
}
}
}
正在进行中,但我希望您能理解主要思想。您需要将db数据提取到一个数组中,该数组可以循环使用深度和子元素,并将数据传递到一个新的多维数组,如下所示:
array(
'1' => array(
'1.2' => array(
'1.2.3' => array(
'1.2.3.4' => array('1.2.3.4.5')
)
)
),
'6' => array(
'6.7' => array('6.7.8')
)
);
然后,您可以循环它,并使用foreach将每个数组作为div进行回显
假设您以array('row'=>array('key'=>'value','etc'=>'more'))的形式发布了从示例表中获取的数据。对于每一行,您需要检查['has_children']
值。如果它的计算结果为true,那么应该将深度作为一个整数,并使用for循环,例如for($i=0;$i$path){
if(is_数组($path)){
//检查是否是第一个。
$class=(strpos('.',$name))?'baz':'bar';
回显“\n\t”;
echo“\n\t{$name}\n\n\n”;
显示($path);
回声“;
}否则{
回显“\n\t”;
echo“\n\t{$path}\n”;
回声“;
}
}
}
正在运行中,但我希望您了解主要思想。您的数据是扁平的,这使得编写递归函数更加困难。递归函数最自然地处理嵌套数据。这花了一段时间,但我能够创建一个部分递归的解决方案来处理平面数据
<?php
$tree = array(array("id"=>1,"depth"=>1,"path"=>"1","has_children"=>true),array("id"=>2,"depth"=>2,"path"=>"1.2","has_children"=>true),array("id"=>3,"depth"=>3,"path"=>"1.2.3","has_children"=>true),array("id"=>4,"depth"=>4,"path"=>"1.2.3.4","has_children"=>true),array("id"=>5,"depth"=>5,"path"=>"1.2.3.4.5","has_children"=>false),array("id"=>6,"depth"=>1,"path"=>"6","has_children"=>true),array("id"=>7,"depth"=>2,"path"=>"6.7","has_children"=>true),array("id"=>8,"depth"=>3,"path"=>"6.7.8","has_children"=>false),array("id"=>9,"depth"=>1,"path"=>"9","has_children"=>false),array("id"=>10,"depth"=>1,"path"=>"10","has_children"=>true),array("id"=>11,"depth"=>2,"path"=>"10.11","has_children"=>false));
header('Content-Type: text/plain');
function print_tree(&$tree, $i, $top_level)
{
$indent = str_repeat(' ', $tree[$i]['depth']);
echo $indent."<div class=\"".($top_level ? 'bar' : 'baz')."\">\n";
echo $indent." <div class=\"qux\">\n";
echo $indent." <p>".$tree[$i]['path']."</p>\n";
echo $indent." </div>\n";
if($tree[$i]['has_children'])
{
print_tree($tree, $i+1, false);
}
echo $indent."</div>\n";
}
echo "<div id=\"foo\">\n";
$count = count($tree);
for($i = 0; $i < $count; ++$i)
{
if($tree[$i]['depth'] == 1)
{
print_tree($tree, $i, true);
}
}
echo "</div>\n";
?>
这将输出:
<div id="foo">
<div class="bar">
<div class="qux">
<p>1</p>
</div>
<div class="baz">
<div class="qux">
<p>1.2</p>
</div>
<div class="baz">
<div class="qux">
<p>1.2.3</p>
</div>
<div class="baz">
<div class="qux">
<p>1.2.3.4</p>
</div>
<div class="baz">
<div class="qux">
<p>1.2.3.4.5</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bar">
<div class="qux">
<p>6</p>
</div>
<div class="baz">
<div class="qux">
<p>6.7</p>
</div>
<div class="baz">
<div class="qux">
<p>6.7.8</p>
</div>
</div>
</div>
</div>
<div class="bar">
<div class="qux">
<p>9</p>
</div>
</div>
<div class="bar">
<div class="qux">
<p>10</p>
</div>
<div class="baz">
<div class="qux">
<p>10.11</p>
</div>
</div>
</div>
</div>
一,
1.2
1.2.3
1.2.3.4
1.2.3.4.5
六,
6.7
6.7.8
九,
十,
10.11
您的数据是扁平的,这使得编写递归函数更加困难。递归函数最自然地处理嵌套数据。这花了一段时间,但我能够创建一个部分递归的解决方案来处理平面数据
<?php
$tree = array(array("id"=>1,"depth"=>1,"path"=>"1","has_children"=>true),array("id"=>2,"depth"=>2,"path"=>"1.2","has_children"=>true),array("id"=>3,"depth"=>3,"path"=>"1.2.3","has_children"=>true),array("id"=>4,"depth"=>4,"path"=>"1.2.3.4","has_children"=>true),array("id"=>5,"depth"=>5,"path"=>"1.2.3.4.5","has_children"=>false),array("id"=>6,"depth"=>1,"path"=>"6","has_children"=>true),array("id"=>7,"depth"=>2,"path"=>"6.7","has_children"=>true),array("id"=>8,"depth"=>3,"path"=>"6.7.8","has_children"=>false),array("id"=>9,"depth"=>1,"path"=>"9","has_children"=>false),array("id"=>10,"depth"=>1,"path"=>"10","has_children"=>true),array("id"=>11,"depth"=>2,"path"=>"10.11","has_children"=>false));
header('Content-Type: text/plain');
function print_tree(&$tree, $i, $top_level)
{
$indent = str_repeat(' ', $tree[$i]['depth']);
echo $indent."<div class=\"".($top_level ? 'bar' : 'baz')."\">\n";
echo $indent." <div class=\"qux\">\n";
echo $indent." <p>".$tree[$i]['path']."</p>\n";
echo $indent." </div>\n";
if($tree[$i]['has_children'])
{
print_tree($tree, $i+1, false);
}
echo $indent."</div>\n";
}
echo "<div id=\"foo\">\n";
$count = count($tree);
for($i = 0; $i < $count; ++$i)
{
if($tree[$i]['depth'] == 1)
{
print_tree($tree, $i, true);
}
}
echo "</div>\n";
?>
这将输出:
<div id="foo">
<div class="bar">
<div class="qux">
<p>1</p>
</div>
<div class="baz">
<div class="qux">
<p>1.2</p>
</div>
<div class="baz">
<div class="qux">
<p>1.2.3</p>
</div>
<div class="baz">
<div class="qux">
<p>1.2.3.4</p>
</div>
<div class="baz">
<div class="qux">
<p>1.2.3.4.5</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bar">
<div class="qux">
<p>6</p>
</div>
<div class="baz">
<div class="qux">
<p>6.7</p>
</div>
<div class="baz">
<div class="qux">
<p>6.7.8</p>
</div>
</div>
</div>
</div>
<div class="bar">
<div class="qux">
<p>9</p>
</div>
</div>
<div class="bar">
<div class="qux">
<p>10</p>
</div>
<div class="baz">
<div class="qux">
<p>10.11</p>
</div>
</div>
</div>
</div>
一,
1.2
1.2.3
1.2.3.4
1.2.3.4.5
六,
6.7
6.7.8
WITH x AS (
SELECT *
,(lag(depth) OVER (ORDER BY id) +1) - depth AS end_divs
,CASE WHEN depth = 1 THEN 'bar' ELSE 'baz' END AS class
,E'\n' || repeat(' ', depth) AS i -- newline + indent
FROM tbl
ORDER BY id
)
SELECT '<div id="foo">'
|| string_agg(
CASE WHEN end_divs > 0 THEN
(SELECT string_agg(repeat (' ', n), E'</div>\n')
FROM generate_series (end_divs,0,-1) n)
ELSE '' END
|| i || '<div class="' || class ||'">'
|| i || ' <div class="qux">'
|| i || ' <p>' || path || '</p>'
|| i || ' </div>'
, E'\n' ORDER BY id
)
|| (SELECT E'\n' || string_agg(repeat (' ', n-1), E'</div>\n')
FROM generate_series((SELECT depth+1 FROM tbl ORDER BY id DESC LIMIT 1)
, 0 , -1) n)
FROM x;
<div id="foo">
<?php
$openingElement = true;
$divsOpened = 0;
$indent = 1;
foreach ($tree as $row) {
if ($openingElement === true) {
print str_repeat(' ', $indent * 4) . '<div class="bar">' . PHP_EOL;
} else {
print str_repeat(' ', $indent * 4) . '<div class="baz">' . PHP_EOL;
}
$indent++;
$divsOpened++;
print str_repeat(' ', $indent * 4) . '<div class="qux">' . PHP_EOL;
$indent++;
print str_repeat(' ', $indent * 4) . '<p>' . $row->path . '</p>' . PHP_EOL;
$indent--;
print str_repeat(' ', $indent * 4) . '</div>' . PHP_EOL;
if ($row->has_children) {
$openingElement = false;
print PHP_EOL;
} else {
for ($i = $divsOpened; $i > 0; $i--) {
print str_repeat(' ', $i * 4) . '</div>' . PHP_EOL;
$indent--;
$divsOpened--;
}
$openingElement = true;
}
}
?>
</div>