Nasıl bir veritabanındaki bir tablodan bir ağaç yapısı oluşturabilir?

3 Cevap php

Ben bir veritabanındaki bir tablodan bir ağaç yapısı oluşturmak için çalışıyorum. Tablo parent_id olan veya 0. Nihai hedefi oluşturulan bir select box, ve düğümler bir dizi var ya, her kayıt, düz saklanır.

Ben kodu şimdiye kadar:

function init($table, $parent_id = 0) 
{

    $sql = "SELECT id, {$this->parent_id_field}, {$this->name_field} FROM $table WHERE {$this->parent_id_field}=$parent_id ORDER BY display_order";

    $result = mysql_query($sql);

    $this->get_tree($result, 0);

    print_r($this->nodes);
    print_r($this->select);
    exit;
}

function get_tree($query, $depth = 0, $parent_obj = null)
{   
    while($row = mysql_fetch_object($query))
    {   
        /* Get node */
        $this->nodes[$row->parent_category_id][$row->id] = $row;

        /* Get select item */
        $text = "";
        if($row->parent_category_id != 0) {
            $text .= "    ";
        }
        $text .= "$row->name";
        $this->select[$row->id] = $text;

        echo "$depth $text\n";

        $sql = "SELECT id, parent_category_id, name FROM product_categories WHERE parent_category_id=".$row->id." ORDER BY display_order";

        $nextQuery = mysql_query($sql);
        $rows = mysql_num_rows($nextQuery);

        if($rows > 0) {
            $this->get_tree($nextQuery, ++$depth, $row);
        }            
    }
}

Neredeyse çalışmıyor, ama oldukça bulunuyor. Herkes bana bunu bitirmek yardımcı olabilir misiniz?

3 Cevap

Ben burada bu çizgi olduğunu düşünüyorum:

if($row->parent_category_id != 0) {
    $text .= "    ";
}

olmalıdır:

while ($depth-- > 0) {
    $text .= "    ";
}

Bunu sadece girintili olmalıdır kaç kez, bir kez değil girinti vardır.

Ve bu çizgi:

$this->get_tree($nextQuery, ++$depth, $row);

olmalıdır:

$this->get_tree($nextQuery, $depth + 1, $row);

Genel veritabanına yuvarlak gezileri (birkaç kullanım durumlar vardır aza indirmek istiyorum, çünkü büyük olasılıkla olsa diğer cevap tavsiye takip ve bir kerede tüm tabloyu yakala, ve sonra bir kerede işlemek gerektiğini unutmayın nerede ) bunu yapıyorsun şekilde çok büyük bir ağaç var, ve bunun küçük bir bölümünü seçerek gibi sanki, daha iyi, ama ben burada bu durumda şüphe

Neredeyse kesinlikle, mevcut yolda devam edilmemelidir. Ağacınızı hiç bile biraz daha alırsa kullanmaya çalıştığınız özyinelemeli yöntem hemen hemen kesinlikle performansını öldürecek. Sık sık ağaç okuma planı varsa muhtemelen yerine komşuluk listesinin iç içe geçmiş bir dizi yapıya bakıyor olmalıdır.

Iç içe bir dizi ile, kolayca tek bir sorgu ile düzgün şekilde iç içe tüm ağaç alabilirsiniz.

Ağaçların aa tartışma için bu soruları bakınız.

http://stackoverflow.com/questions/169817/is-it-possible-to-query-a-tree-structure-table-in-mysql-in-a-single-query-to-any

http://stackoverflow.com/questions/544632/implementing-a-hierarchical-data-structure-in-a-database

http://stackoverflow.com/questions/192220/what-is-the-most-efficient-elegant-way-to-parse-a-flat-table-into-a-tree

    $this->nodes[$row->parent_category_id][$row->id] = $row;

Bu hattı SİPARİŞ display_order TARAFINDAN yok ediyor. Bunu değiştirin

    $this->nodes[$row->parent_category_id][] = $row;

Bir sonraki konu bunun $ row-> parent_category_id parçasıdır. Sadece satır-> parent_id $ gerekmiyor mu?

EDIT: Oh, ben yakından yeterince kaynak okumadım. WHERE yan tümcesi kurtulun. Bir kerede tüm tabloyu okuyun. Sen ağaca ikinci kez süreç sonrası gerekir. Önce diziler bir liste halinde veritabanını okumak. Sonra da çıktı yapmak için ardışık dizi işlemek.

Sizin dizi bu gibi görünmelidir:

 Array(0 => Array(1 => $obj, 5 => $obj), 
       1 => Array(2 => $obj),
       2 => Array(3 => $obj, 4 => $obj),
       5 => Array(6 => $obj) );

 function display_tree() {
      // all the stuff above
      output_tree($this->nodes[0], 0); // pass all the parent_id = 0 arrays.
 }

 function output_tree($nodes, $depth = 0) {
     foreach($nodes as $k => $v) {
         echo str_repeat(' ', $depth*2) . $v->print_me();
         // print my sub trees
         output_tree($this->nodes[$k], $depth + 1);
     }
 }

 output:
 object 1
   object 2
     object 3
     object 4
 object 5
   object 6