0

PHPでマルチレベルメニューを作ろうとしていますが、htmlが正しく出力できません。

まず、データベースからデータを抽出し、「sort_id」と「id」の後に並べ替えて、配列に格納します。

DB構造:

id | parent_id | sort_id | title
---------------------------------
1  |     0     |    0    | test1
2  |     1     |    1    | test2
3  |     1     |    0    | test3
4  |     0     |    1    | test4
5  |     2     |    0    | test5

PHP コード

function hasChildren( $id, $data ) {
  foreach  ($data as $d ) {
    if ( $d['parent_id'] == $id ) {
        return true;
        break;
    }
  }
}

function menu ($arr) {
  foreach ( $arr as $d ) {
    if( is_array($d) && $d['parent_id'] == 0 ) {
        echo "<li><a href={$d['link']}>{$d['title']}</a>";
        if ( hasChildren ($d['id'], $arr) ) echo "<ul>";
    }

    foreach ( $arr as $row ) {
       if ( is_array($row) ) {

            if( $row['parent_id'] == $d['id'] ) {
                if ( hasChildren ($row['id'], $arr) ) {
                    echo "<li><a href={$row['link']}>{$row['title']}</a><ul>";
                } else echo "<li><a href={$row['link']}>{$row['title']}</a>";

                menu($row);

                if ( hasChildren ($row['id'], $arr) ) {
                    echo "</ul></li>";
                } else echo "</li>";
            }
        }
    }
    if ( is_array($d) && $d['parent_id'] == '0' ) {
        if ( hasChildren ($d['id'], $arr) ) echo "</ul>";
        echo "</li>";
    }
  }
}

HTML出力

<li>
   <a href="http://localhost">test1</a>
   <ul>
      <li><a href="http://localhost/2">test3</a></li>
      <li><a href="http://localhost/1">test2</a>
      <ul></ul>
      </li>
   </ul>
</li>
<li><a href="http://localhost/5">test5</a></li>
<li><a href="http://localhost/4">test4</a></li>

「test2」が「ul」タグを開閉した後

'test5' は 'test2' の子であり、親ではありません

これが最善の方法ではないかもしれないことはわかっていますが、誰かが私が間違っていることを教えてくれますか?

4

2 に答える 2

1

1) メニュー($row); 役に立たない、何もしないから

2) 再帰を適用する場合は、次のように記述する必要があります。

function menu($arr, $parent) {
    $open = 0;
    foreach ($arr as $row) {
        if ($parent == $row['parent_id']) {
            echo ($open?'':'<ul>')."<li><a href={$row['link']}>{$row['title']}</a>";
            menu($arr, $row['id']);
            echo "</li>";
            $open++;
        }
    }
    if ($open) {
        echo "</ul>";
    }
}

menu($array, 0);
于 2013-09-16T19:18:30.627 に答える
1

データベース テーブルを変更できる場合は、MPTT (変更された事前注文ツリー トラバーサル) を使用してデータを保存することを強くお勧めします。それは多くの問題を解決します**。これは本当に良い例です: http://www.sitepoint.com/hierarchical-data-database-2/

CakePHP の連中は、parent_id フィールドと組み合わせて MPTT を使用しています。

データベースを変更できない、または変更したくない場合は、PHP を使用してデータを事前に並べ替え、配列内で子が親の後に配置され、メニューを出力するようにします。最初に uasort を使用したテスト コードをいくつか作成しましたが、ロジックはすぐに複雑になります。

MPTT を使用する場合は回答を受け入れるか、2 番目の解決策で助けが必要な場合はコメントを追加してください。

** - ノードの深さ、ノードへのパス、ツリー全体は簡単に導出でき、これを行うコードは既に存在します。

于 2013-09-16T19:42:19.613 に答える