2

カテゴリデータを持つデータベースにテーブルがあります:

id タイトル 親
1 カテゴリ 1 0
2 カテゴリー 2 2
3 カテゴリー 3 3
4 カテゴリ 4 0

各親は、親の行 ID を持つことができます。

たとえば、カテゴリ 3 は、カテゴリ 1 の子であるカテゴリ 2 の子です。

カテゴリー1
   カテゴリー2
      カテゴリー3

カテゴリー4

1 - このテクニックを操作するより良い方法はありますか? 2 - 私の実装では、1 つの SQL クエリですべての行をフェッチし、再帰関数を使用して多次元配列を作成し、マルチレベル foreach を使用してそれをループしてメニューなどを作成します。PHP SPL を使用するより良い方法が必要です。

完全なメニューまたは次のようなアイテムパスを作成したい:

カテゴリ 1 -> カテゴリ 2 -> など。

各行にカテゴリレベルを保持するグリッドを作成します。

4

2 に答える 2

3

データが厳密に階層化されており、そのように見える場合は、データを格納するために Modified Preorder Tree Traversal メソッドをお勧めします。

この正確な問題について説明している優れた記事が Sitepointにあります。1 ページ目で説明した Adjacency List モデルを使用しているように見えますが、このタイプのデータの読み取り負荷の高いストレージには、MPTT の方がはるかに効率的です。

2 ページをチェックして、例を確認してください。本当に素晴らしい建築物です。

于 2009-05-08T03:20:28.853 に答える
1

私は最近、単一のクエリと単一の while ループを使用して、同様のことを行いました。参照を使用して、フラットなデータ構造 (配列) によってツリー データ構造 (配列) を構築します。SPL の必要性は感じなかったので、SPL は関係ありません。より良い配色のGistがGitHubにあります:)

/**
* Each element in the return array has a 'data' key, holding category data,
* like name, and a 'children' key holding its subcategories.
*
* @param resource $resource MySQL resource resulted from mysql_query
* @param string $id_key Name of the 'id' field
* @param string $parent_id_key Name of the 'parent_id' field
* @param boolean $use_cache Use cached result from previous calls. Defaults to TRUE
* @return array
*/
function categories($resource, $id_key, $parent_id_key, $use_cache = true) {
    // Cache the categories in a static local variable. This way, the query
    // will be executed just for the first function call. Subsequent calls
    // will return imediatelly, unless you tell it not to.
    static $tree = array();

    if ($tree && $use_cache) {
        return $tree;
    }

    // Flat representation of the categories for fast retrieval using array
    // keys. Each element will be referenced in the $tree array. This
    // allows to build a tree data structure using a flat one.
    $flat = array();

    // Reset the $tree, in case $use_cache=false in a subsequent call
    $tree = array();

    while ($row = mysql_fetch_object($resource)) {
        $flat[$row->$id_key] = array(
            'data' => $row,
            'children' => array(),
        );

        if (array_key_exists($row->$parent_id_key, $flat)) {
            // Assign children by reference so that possible subcategories of
            // this one will appear in the tree structure ($tree)
            $flat[$row->$parent_id_key]['children'][] =& $flat[$row->$id_key];
        }

        if ($row->$parent_id_key == 0) {
            // Assign by reference for synchronizing $flat with $tree;
            $tree[] =& $flat[$row->$id_key];
        }
    }

    return $tree;
}

また、関数はデータベースの構造から分離されています。id フィールドを表す文字列と、parent_id フィールドを表す文字列である mysql_query リソースを渡す必要があります。悪い点は、mysql_fetch_object への呼び出しを使用するため、PHP mysql 拡張機能に結合されていることです。おそらく改善される可能性があります。

他のいくつかの利点は、4 番目の (ブール値) パラメータであるキャッシュを無効にするように指示しない限り、後続の呼び出しの結果をキャッシュすることです。

見て、それがあなたに役立つかどうかを確認してください。

于 2009-05-08T01:37:57.493 に答える