6

私はたくさんのカテゴリーのデータベースを持っています、いくつかは子供です:

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Home Improvement
            [slug] => Home-Improvement
            [parent] => 
            [user_id] => 1
            [order] => 1
        )

    [1] => Array
        (
            [id] => 2
            [name] => Asbestos Abatement & Removal
            [slug] => Asbestos-Abatement-Removal
            [parent] => 1
            [user_id] => 1
            [order] => 8
        )

    [2] => Array
        (
            [id] => 3
            [name] => Asphalt & Asphalt Products
            [slug] => Asphalt-Asphalt-Products
            [parent] => 1
            [user_id] => 1
            [order] => 9
        )

    [3] => Array
        (
            [id] => 4
            [name] => Bathroom
            [slug] => Bathroom
            [parent] => 1
            [user_id] => 1
            [order] => 10
        )

    [4] => Array
        (
            [id] => 5
            [name] => Kitchen Cabinets
            [slug] => Kitchen-Cabinets
            [parent] => 1
            [user_id] => 1
            [order] => 11
        )

    [5] => Array
        (
            [id] => 6
            [name] => Ceilings
            [slug] => Ceilings
            [parent] => 1
            [user_id] => 1
            [order] => 12
        )

    [6] => Array
        (
            [id] => 7
            [name] => Cleaning
            [slug] => Cleaning
            [parent] => 1
            [user_id] => 1
            [order] => 13
        )

    [7] => Array
        (
            [id] => 8
            [name] => Closet Organizers & Accessories
            [slug] => Closet-Organizers-Accessories
            [parent] => 1
            [user_id] => 1
            [order] => 14
        )

    [8] => Array
        (
            [id] => 9
            [name] => Concrete
            [slug] => Concrete
            [parent] => 1
            [user_id] => 1
            [order] => 15
        )

    [9] => Array
        (
            [id] => 10
            [name] => Contractors & Service Providers
            [slug] => Contractors-Service-Providers
            [parent] => 1
            [user_id] => 1
            [order] => 16
        )

私が出力しようとしているのは次のようなものです。

<ul>
    <li>Parent
        <ul>
            <li>Child</li>
        </ul>
    </li>
    <li>Parent with no Children</li>
</ul>

PHPで再帰ツリースクリプトを作成しようとしていますが、行き詰まります。これが私がこれまでに持っているものです。私はelse:とendifの間で何をすべきかについて立ち往生しています。foreachで。(そして、ここで読みやすくするために、その構文を使用しています。)何か提案はありますか?

echo $this->categories->makeTree(0, $this->db->get('categories')->result_array());

public static function makeTree($parent, $array)
{
  if (!is_array($array)) return '';

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];
        else:

        endif;
    endif;

    $output .= '</li>';
  endforeach;

  $output .= '</ul>';
  return $output;
}

編集1

foreachループでデータベース呼び出しを行っていますが、これを機能させることができました。これはおそらく最善のアイデアではありません。

public function makeTree($parent, $array)
{
  if (!is_array($array)) return FALSE;

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];

            $subcategories = ci()->db->get_where('categories', array('parent' => $value['id']));

            if ($subcategories->num_rows() > 0):
                $output .= $this->makeTree($value['id'], $subcategories->result_array());
            endif;
        else:
            $output .= $value['name'];
            $output .= '</li>';
        endif;
    endif;

  endforeach;

  $output .= '</ul>';
  return $output;
}

編集2

これが私の最終的な解決策であり、DBクエリを実行する代わりに配列を再利用します。

public function makeTree($parent, $array)
{
  if (!is_array($array) OR empty($array)) return FALSE;

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];

            $matches = array();

            foreach($array as $subkey => $subvalue):
                if ($subvalue['parent'] == $value['id']):
                    $matches[$subkey] = $subvalue;
                endif;
            endforeach;

            $output .= $this->makeTree($value['id'], $matches);

        else:
            $output .= $value['name'];
            $output .= '</li>';
        endif;
    endif;

  endforeach;

  $output .= '</ul>';

  return $output;
}
4

5 に答える 5

10

これは答えられたようですが、ここを見てください。示されている関数を使用すると、1回の反復でフラットデータをネストされたデータに変換できます。そのネストされたデータからul-listを作成するのは非常に簡単です。例えば:

function nested2ul($data) {
  $result = array();

  if (sizeof($data) > 0) {
    $result[] = '<ul>';
    foreach ($data as $entry) {
      $result[] = sprintf(
        '<li>%s %s</li>',
        $entry['name'],
        nested2ul($entry['children'])
      );
    }
    $result[] = '</ul>';
  }

  return implode($result);
}

echo nested2ul(array(flat2nested( $yourFlatData ));

このアプローチの良いところは、子要素を見つけるためだけに入力データを何度も繰り返す必要がないことです。

于 2012-09-06T08:02:33.853 に答える
2

これが私の最終的な解決策であり、DBクエリを実行する代わりに配列を再利用します。より良い解決策がある場合は、投稿してください!

public function makeTree($parent, $array)
{
  if (!is_array($array) OR empty($array)) return FALSE;

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];

            $matches = array();

            foreach($array as $subkey => $subvalue):
                if ($subvalue['parent'] == $value['id']):
                    $matches[$subkey] = $subvalue;
                endif;
            endforeach;

            $output .= $this->makeTree($value['id'], $matches);

        else:
            $output .= $value['name'];
            $output .= '</li>';
        endif;
    endif;

  endforeach;

  $output .= '</ul>';

  return $output;
}
于 2012-09-05T19:47:10.927 に答える
1

私はいつもこのようなものを使用します、注意してください

最初のこのコードは、非推奨のmysql_*を使用しています。

2番目に、levelという名前のデータベースフィールドが1つ必要です。NULLの場合はメインカテゴリであり、番号がある場合は、その番号をidとして持つカテゴリのサブカテゴリです。

function getFamilies($level = 0) {
    $level++;
    $sql = "SELECT id from families WHERE level IS NULL";
    if (mysql_num_rows($result) > 0) {
        echo "<ul>";
            while($row = mysql_fetch_assoc($result)) {
                echo "<li>".$row['id'];
                    getSubFamilies($level, $row['id']);
                echo "</li>";
            }
        echo "</ul>";
    }
}

function getSubFamilies($level, $id) {
    $level++;
    $sqlSubFamilies = "SELECT id  FROM families WHERE level = ".$id."";
    $resultSubFamilies = mysql_query($sqlSubFamilies);
    if (mysql_num_rows($resultSubFamilies) > 0) {
        echo = "<ul>";
            while($rowSubFamilies = mysql_fetch_assoc($resultSubFamilies)) {
                echo "<li>".$rowSubFamilies['id'];
                    getSubFamilies($level, $rowSubFamilies['id']);
                echo "</li>";
            }
        echo "</ul>";
    }
}

getFamilies($level = 0);
于 2012-09-05T17:09:58.133 に答える
0

これを試して:

$cats = $this->db->get('categories')->result_array();

echo $this->categories->makeTree(0, $cats);

public static function makeTree($parent, $array)
{
  if (!is_array($array)) return '';

  $output = '<ul>';

  foreach($array as $key => $value):
    if ($value['parent'] == $parent):
        $output .= '<li>';

        if ($value['parent'] == NULL):
            $output .= $value['name'];
        else:

        endif;
    endif;

    $output .= '</li>';

    $output .= $this->categories->makeTree($value['parent'], $cats);

  endforeach;

  $output .= '</ul>';
  return $output;
}
于 2012-09-05T16:55:38.183 に答える
-1

この匿名関数を使用する方法は非常に簡単だと思います。

//--------------------------- PRINT NESTED CATEGORIES
$cats_childs = array();

$q = $db->query("SELECT id, parent, name FROM categories");

while ($r = $db->row($q))
{
    $cats_childs[$r['parent']][$r['id']] = $r;
}

$nested2ul = function($data) use (&$nested2ul, &$cats_childs) {
    if (!empty($data)) {
        echo '<ul>';
        foreach ($data as $r) {
            echo '<li>';
            echo $r['name'];
            $flat2ul($cats_childs[$r['id']]);
            echo '</li>';
        }
        echo '</ul>';
    }
};

echo $nested2ul($cats_childs[0]);
于 2017-09-07T00:19:23.187 に答える