سؤال

أنا إنشاء هيكل شجرة من فئات مع parentid التي يمكن استدعاؤها من الأطفال في مثل هذه الطريقة:

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

مما أدى إلى هذا:

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

مما يعني 3 هو طفل من 2, الذي هو طفل من 1.

عندما تحاول الحصول على هذه الفكرة (مع -> إظهار ما العلاقات بين) إلى الصف الثاني (1 -> 2) ولكن لا ثالث (1->2->3) لأن من وظيفة حلقات يمكنني استخدام لذلك.

//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>';
}

أود أمرين للتغيير:

  1. أن تولد تلقائيا شجرة الحجم حسب الضرورة.
  2. في حين الحلقات لدي لتحديد $النتيجة مرتين (مرة واحدة $النتيجة مرة واحدة $result2) أن تجعل من العمل.هذه $النتيجة يكون بالضبط نفس قاعدة البيانات-الاستعلام:
    SELECT ID,name,parentid FROM categories

جلب النتائج من.أود أن تعلن فقط هذا مرة واحدة.



شكرا لجميع إجابات جيدة.لقد ذهبت مع أسهل وأقل رمز لتنفيذ النهج:

$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>';
}
هل كانت مفيدة؟

المحلول

إذا كنت تريد حقا أن تفعل hierachies مع الوالدين معرفات(مناسبة فقط عدد قليل من البنود/hierachies)

أنا تعديل التعليمات البرمجية الخاصة بك قليلا(أنا لم تختبر لذلك قد يكون هناك بعض أخطاء في بناء الجملة):

//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>';
}

للإجابة على تعليقك:

$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>';
}

يطبع:

العامة ->

العامة -> أدوات ->

العامة -> أدوات -> اي فون ->

نصائح أخرى

بدلا من PHP تنظيم العناصر في شجرة ، لماذا لا تطلب من قاعدة البيانات أن تفعل ذلك بالنسبة لك ؟ لقد وجدت هذا المادة على البيانات الهرمية أن تكون جيدة جدا و الأمثلة هي متطابقة تقريبا إلى لك.


تحرير

SQL للحصول على كامل الشجرة باستخدام الجوار نموذج ليست مثالية.كما توضح هذه المادة فإنه يتطلب الكثير بدلا من ينضم حتى صغيرة الهرمي.هو أنه ليس من الممكن بالنسبة لك لاستخدام مجموعة متداخلة النهج ؟ SQL يبقى نفسه بغض النظر عن حجم الهرم و إدراج وحذف يجب أن لا يكون من الصعب جدا أيضا.

ربما أسهل مع OOP.مجرد نوع الاستعلام عن طريق parentId

ملاحظة:على listChildren طريقة المطبوعة في أسفل هناك فقط هي المدرجة بشكل صحيح.لم تفسر السؤال الذي عرض مهم.

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";
    }
}

إذا كنت تستخدم كيو مثل قاعدة البيانات ، يمكنك استخدام connectby() وظيفة لإنشاء مجموعة سجلات:

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

أنا أحب هذه الوظيفة ، واستخدام كل الوقت في قانون بلدي.يمكن أن تفعل بعض أشياء قوية جدا, سريع جدا, و لا يجب على يسار/يمين القيم مثل (الجوار نموذج).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top