У меня есть таблица SQL для системы меню. Он имеет «id» в качестве индекса, поле «display» и поле «parent». Вот эти данные:
id, display, parent
1, File, 0
2, View, 0
3, Window, 0
4, Open, 1
5, Save, 1
6, Export, 1
7, Export to Image, 6
8, Export to PDF, 6
9, JPEG, 7
10, PNG, 7
Я хотел иметь функцию для возврата иерархии меню в формате выбора HTML. Желаемый результат будет выглядеть так:
<option value='1'>File</option>
<option value='4'>-- Open</option>
<option value='5'>-- Save</option>
<option value='6'>-- Export</option>
<option value='7'>---- Export to Image</option>
<option value='9'>------ JPEG</option>
<option value='10'>------ PNG</option>
<option value='8'>---- Export to PDF</option>
<option value='2'>View</option>
<option value='3'>Window</option>
Это функция, которую я придумал:
function SelectPage($pdo, $default = "", $depth = 0, $id = 0, $opts = "") {
$sql = $pdo->prepare("SELECT id,display FROM pages WHERE parent = ?");
$sql->execute(array($id));
while ($row = $sql->fetch(PDO::FETCH_ASSOC)) {
$opts .= "<option value='{$row["id"]}'>";
$opts .= trim(str_repeat("--", $depth) . " ");
$opts .= "{$row["display"]}</option>";
$tmp = SelectPage($pdo, $default, ($depth + 1), $row["id"], $opts);
$opts = $tmp;
}
return $opts;
}
Это работает, но я сомневаюсь, насколько это эффективно. Мне было интересно, если бы был способ сделать запрос SQL, который возвращает их уже в правильном порядке, чтобы я мог избежать выполнения циклических вызовов сам по себе?
Не используйте рекурсив с вашим оператором sql. В одном запросе возьмите все категории в массив следующим образом:
$categories = array(
array(
'id' => 1,
'name' => 'File',
'parent' => 0
),
... etc.
);
Затем используйте эту простую функцию. Вы можете изменить, если хотите.
function isSubCategory( $id, $cats )
{
foreach( $cats as $cat )
{
if( $id != $cat['id'] && $id == $cat['parent'] )
return true;
}
return false;
}
echo '<select>';
function getRecursiveTree( $parent, $cats, $level = -1 )
{
$separator = '-';
foreach( $cats as $i => $cat )
{
if( $cat['parent'] == $parent )
{
$level++;
if( isSubCategory( $cat['id'], $cats ) )
{
echo '<option value="',$cat['id'],'">', str_repeat( $separator, $level ) , $cat['name'],'</option>' . PHP_EOL;
getRecursiveTree( $cat['id'], $cats, $level );
}
else
{
echo '<option value="',$cat['id'],'">', str_repeat( $separator, $level ) , $cat['name'],'</option>' . PHP_EOL;
}
$level--;
}
}
}
echo ( getRecursiveTree( 0, $k ) );
echo '</select>';
Других решений пока нет …