nasıl döngüye elemanları üzerinde döngü için?

4 Cevap php

Ben böyle bir şekilde çocukların aranabilecek parentid ile 'kategorilerinin bir ağaç yapısı oluşturma:

ID | Name | ParentID
1    1      0
2    2      1
3    3      2
4    4      1

Bu şekilde sonuçlanır:

1 = 1
2 = 1 -> 2
3 = 1 -> 2 -> 3
4 = 1 -> 4

1 bir çocuk hangi 3 is a child of 2 demektir.

Ben sadece ikinci sınıfa olsun çünkü döngü fonksiyonu - (> 3 - 1 -> 2) (1> 2) ancak üçüncü - bu fikri (> ilişkiler ayarlanır göstermek için birlikte) almaya çalışırken Ben bunun için kullanın.

//put all ID's in an array
while ($row2 = $connector->fetchArray($result2)){
 $id = $row2['ID'];
 $parents[$id] = $row2['name'];
}

// show the tree-structure
while ($row = $connector->fetchArray($result)){
    if($row['parentid']!=0)echo $parents[$row['parentid']].' -> ';
    echo $row['name'].' -    ';
    echo '<br>';
}

Ben değiştirmek için iki şey istiyorum:

  1. kodu otomatik olarak bir ağaç olarak gerekli büyüklükte üretmek var.
  2. while döngülerinde i çalışması için iki kez ($ sonucunda, bir zamanlar $ result2) $ sonucu seçmek zorunda. Bu $ tamamen aynı veritabanı sorgu var neden:
    SELECT ID,name,parentid FROM categories

to fetch results from. I'd like to only declare this once.



Thanks for all the good answers. I've gone with the easiest, less-code-to-implement approach:

$result = $connector->query('SELECT ID,name,parentid FROM categories');

// Get an array containing the results.
$parents = array();
while ($row = $connector->fetchArray($result)){
  $id = $row['ID'];
  $parents[$id] = array('ID' => $row['ID'],'name' => $row['name'],'parentid' => $row['parentid']);
}

foreach ($parents as $id => $row){
  $pid=$id;
  $arrTmp= array();
  do {      // iterate through all parents until top is reached
    $arrTmp[]=$pid;
    $pid = $parents[$pid]['parentid'];
  }while ($pid != 0);
    $arrTmp = array_reverse($arrTmp);
  foreach($arrTmp as $id){
    echo $parents[$id]['name'].' -&gt; ';
    }
  echo '<br>';
}

4 Cevap

Eğer gerçekten (sadece küçük öğeler / hierachies sayısı için uygundur) ebeveyn kimlikleri ile hierachies yapmak istiyorsanız

Ben senin kodunu biraz (bazı sözdizimi hataları olabilir o yüzden test etmedi) değiştirilmiştir:

//put all recordsets in an array to save second query
while ($row2 = $connector->fetchArray($result2)){
  $id = $row2['ID'];
  $parents[$id] = array('name' => $row2['name'],'parent' => $row2['parentid']);
}

// show the tree-structure
foreach ($parents as $id => $row){
  $pid = $row['parentid'];
  while ($pid != 0){      // iterate through all parents until top is reached
    echo $parents[$pid]['name'].' -&gt; ';
    $pid = $parents[$pid]['parentid'];
  }
  echo $parents[$id]['name'].' -    ';
  echo '<br>';
}

Yorum cevaplamak için:

$parents = array();
$parents[2] = array('ID'=>2,'name'=>'General','parentid'=>0); 
$parents[3] = array('ID'=>3,'name'=>'Gadgets','parentid'=>2); 
$parents[4] = array('ID'=>4,'name'=>'iPhone','parentid'=>3); 

foreach ($parents as $id => $row){
  $pid=$id;
  $arrTmp= array();
  do {      // iterate through all parents until top is reached
    $arrTmp[]=$pid;
    $pid = $parents[$pid]['parentid'];
  }while ($pid != 0);
    $arrTmp = array_reverse($arrTmp);
  foreach($arrTmp as $id){
    echo $parents[$id]['name'].' -&gt; ';
    }
  echo '<br>';
}

Çıkış yazdırır:

Genel ->

Genel -> Gadgets ->

Genel -> Gadgets -> iPhone ->

PHP bir ağaca öğeleri organize olması yerine, neden sizin için bunu yapmak için veritabanını sormuyorsun? Ben bu article on hierarchical data çok iyi bulundu ve örnekler sizin için hemen hemen aynıdır.


EDIT

Komşuluk Modeli kullanılarak tam ağacı almak için SQL ideal değildir. Makale, hatta küçük bir hiyerarşi için oldukça katıldı bir sürü gerektirir olarak açıklıyor. Eğer iç içe Set yaklaşımı kullanmak mümkün değil mi? SQL olursa olsun hiyerarşi büyüklüğü aynı kalır ve ya çok zor olmamalı INSERT ve DELETE.

Belki OOP ile daha kolay. Sadece parentId tarafından sorgu sıralamak

Not: altındaki ListChildren yöntemi ve çıktının doğru listelenir göstermek için orada olduğunu. Ben ekran önemli olduğunu soruyu yorumlamak vermedi.

class Element {
    public $id;
    public $name;
    public $parent = null;
    public $children = array();

    public function __construct($id, $name)
    {
    	$this->id = $id;
    	$this->name = $name;
    }

    public function addChild($element)
    {
    	$this->children[$element->id] = $element;
    	$element->setParent($this);
    }

    public function setParent($element)
    {
    	$this->parent = $element;
    }

    public function hasChildren()
    {
    	return !empty($this->children);
    }

    public function listChildren()
    {
    	if (empty($this->children)) {
    		return null;
    	}

    	$out = array();
    	foreach ($this->children as $child) {
    		$data = $child->id . ':' . $child->name;
    		$subChildren = $child->listChildren();
    		if ($subChildren !== null) {
    			$data .= '[' . $subChildren . ']';
    		}
    		$out[] = $data;
    	}
    	return implode(',', $out);
    }
}

$elements = array();
$noParents = array();
while ($row = $connector->fetchArray($result)) {
    $elements[$row['id']] = $element = new Element($row['id'], $row['name']);

    if (isset($elements[$row['parent']])) {
    	$elements[$row['parent']]->addChild($element);
    } else {
    	$noParents[] = $element;
    }
}

foreach ($noParents as $element) {
    if ($element->hasChildren()) {
    	echo "Element {$element->id} has children {$element->listChildren()}.\n";
    } else {
    	echo "Element {$element->id} has no children.\n";
    }
}

Eğer veritabanı olarak PostgreSQL kullanıyorsanız, size kayıt kümesi oluşturmak için connectby () işlevini kullanabilirsiniz:

SELECT * 
FROM connectby('tableName', 'id', 'parent_id') 
    AS t(keyid text, parent_keyid text, level int);

Ben bu işlevi seviyorum ve benim kod her zaman kullanın. Bu çok hızlı, bazı çok güçlü şeyler yapabilirsiniz, ve (adjacency modeli) gibi sağ / sol değerlerini korumak değil yok.