我有一个带有树数据结构的MySQL表。字段为_id
,name
和parentId
。当记录没有父级时,parentId
默认为0.这样我就可以构建一个数组,然后递归打印每条记录。
构建的数组如下所示:
Array
(
[1] => Array
(
[parentId] => 0
[name] => Countries
[_id] => 1
[children] => Array
(
[2] => Array
(
[parentId] => 1
[name] => America
[_id] => 2
[children] => Array
(
[3] => Array
(
[parentId] => 2
[name] => Canada
[_id] => 3
[children] => Array
(
[4] => Array
(
[parentId] => 3
[name] => Ottawa
[_id] => 4
)
)
)
)
)
[5] => Array
(
[parentId] => 1
[name] => Asia
[_id] => 5
)
[6] => Array
(
[parentId] => 1
[name] => Europe
[_id] => 6
[children] => Array
(
[7] => Array
(
[parentId] => 6
[name] => Italy
[_id] => 7
)
[11] => Array
(
[parentId] => 6
[name] => Germany
[_id] => 11
)
[12] => Array
(
[parentId] => 6
[name] => France
[_id] => 12
)
)
)
[8] => Array
(
[parentId] => 1
[name] => Oceania
[_id] => 8
)
)
)
)
使用递归打印无序列表<ul>
非常简单。这是我使用的功能:
function toUL ($arr) {
$html = '<ul>' . PHP_EOL;
foreach ( $arr as $v ) {
$html.= '<li>' . $v['name'] . '</li>' . PHP_EOL;
if ( array_key_exists('children', $v) ) {
$html.= toUL($v['children']);
}
}
$html.= '</ul>' . PHP_EOL;
return $html;
}
但是我坚持以树形结构方式打印<select>
:
Countries
-- America
---- Canada
------ Ottawa
-- Asia
-- Europe
---- Italy
---- Germany
---- France
-- Oceania
我想打印--
的次数与元素的深度一样多,但我不知道如何计算深度。
我的问题是:是否可以在不知道深度的情况下构建<select>
?
提前谢谢。
答案 0 :(得分:6)
传递一个参数来计算迭代次数$pass
function toUL ($arr, $pass = 0) {
$html = '<ul>' . PHP_EOL;
foreach ( $arr as $v ) {
$html.= '<li>';
$html .= str_repeat("--", $pass); // use the $pass value to create the --
$html .= $v['name'] . '</li>' . PHP_EOL;
if ( array_key_exists('children', $v) ) {
$html.= toUL($v['children'], $pass+1);
}
}
$html.= '</ul>' . PHP_EOL;
return $html;
}
答案 1 :(得分:3)
您的问题已在SPL中解决。 RecursiveIteratorIterator
Docs包含有关某个项目深度的信息:
$it = new RecursiveIteratorIterator(new RecursiveArrayIterator($array), SELF_FIRST);
foreach ($it as $key => $element)
{
if ($key !== 'name') continue;
$inset = str_repeat('--', $it->getDepth());
printf('<option>%s %s</option>', $inset, $element);
}
答案 2 :(得分:1)
function toSelect($arr, $depth = 0) {
$html = '';
foreach ( $arr as $v ) {
$html.= '<option>' . str_repeat("--", $depth) . $v['name'] . '</option>' . PHP_EOL;
if ( array_key_exists('children', $v) ) {
$html.= toSelect($v['children'], $depth++);
}
}
return $html;
}
答案 3 :(得分:1)
我的最终解决方案(感谢Starx和varan):
function toSelect ($arr, $depth=0) {
$html = '';
foreach ( $arr as $v ) {
$html.= '<option value="' . $v['_id'] . '">';
$html.= str_repeat('--', $depth);
$html.= $v['name'] . '</option>' . PHP_EOL;
if ( array_key_exists('children', $v) ) {
$html.= toSelect($v['children'], $depth+1);
}
}
return $html;
}
echo '<select>';
echo toSelect($array);
echo '</select>';
即使RecursiveIteratorIterator
解决方案也很好(感谢hakre)。
答案 4 :(得分:1)
嗨,大家好,你可以这样做:
我有$tree
的这个对象:
Array
(
[0] => stdClass Object
(
[id] => 1
[nombre] => Category 1
[subcategorias] => Array
(
[0] => stdClass Object
(
[id] => 4
[nombre] => Category 1.1
)
)
)
[1] => stdClass Object
(
[id] => 2
[nombre] => Category 2
)
[2] => stdClass Object
(
[id] => 3
[nombre] => Category 3
[subcategorias] => Array
(
[0] => stdClass Object
(
[id] => 5
[nombre] => Category 3.1
[subcategorias] => Array
(
[0] => stdClass Object
(
[id] => 6
[nombre] => Category 3.1.1
)
)
)
)
)
)
然后是如何为HTML选择创建数组:
$tree=array();// PUT HERE YOUR TREE ARRAY
$arrayiter = new RecursiveArrayIterator($tree);
$iteriter = new RecursiveIteratorIterator($arrayiter);
$lista=array();
$i=0;
foreach ($iteriter as $key => $value)
{
$id=$iteriter->current();
$iteriter->next();
$nivel=$iteriter->getDepth();
$nombre=str_repeat('-',$nivel-1).$iteriter->current();
$lista[$id]=$nombre;
}
你会得到这样的东西:
Array
(
[1] => Category 1
[4] => --Category 1.1
[2] => Category 2
[3] => Category 3
[5] => --Category 3.1
[6] => ----Category 3.1.1
)
然后你只需要用一个简单的foreach为select创建选项。
答案 5 :(得分:0)
您可以将长度传递给函数并在递归调用时递增它,然后使用变量$length
来确定深度
function toUL ($arr, $length = 0) {
$html = '<ul>' . PHP_EOL;
foreach ( $arr as $v ) {
$html.= '<li>' . $v['name'] . '</li>' . PHP_EOL;
if ( array_key_exists('children', $v) ) {
$html.= toUL($v['children'], $length++);
}
}
$html.= '</ul>' . PHP_EOL;
return $html;
}
这就是我通常用来跟踪递归深度,通常可以完成工作
答案 6 :(得分:0)
function toUL ($arr, $depth = 0) {
// ...
$html .= toUL($v['children'], $depth+1);
答案 7 :(得分:0)
您可以使用optgroup作为迭代器。 例如:
<select name="list">
<option value=1>1st option</option>
<optgroup>
<option value=10>1st on 1st group</option>
</optgroup>
</select>
如果你想要php,你可以试试这个:
<?PHP
function toSELECT($arr,$depth=0)
{
$html="";
if(is_array($arr))
{
$html.=($depth==0)?"<select name='html'>\n":"";
foreach ($arr as $key=>$value)
{
if(is_array($arr[$key]))
{
$html.=str_repeat("\t",$depth)."<optgroup>\n";
$html.=str_repeat("\t",$depth).toHTML($arr[$key],$depth+1);
$html.=str_repeat("\t",$depth)."</optgroup>\n";
}
else
{
$html.=str_repeat("\t",$depth)."<option value='".$value."'>".$key."</option>\n";
}
}
$html.=($depth==0)?"</select>\n":"";
}
return $html;
}
?>