繁体   English   中英

从多个 mysql 表中提取的数据中使用 php 显示 4 级层次结构

[英]Display 4 level hierachy with php from data pulled from multiple mysql table

首先,我不是任何类型的程序员,我玩 php 和 mysql 是为了自娱自乐,但此时我有一个问题,我不知道如何解决。

我试图在php中显示一个分类单元树,基本上

属 亚属 种 亚种

我设法做到了这一点,我使用从数据库中截断样本以保持可读性。

Genus: Agonum Bonelli, 1810
   Species: Agonum patinale Bates, 1882
   Species: Agonum scutiferum Bates, 1878
   Species: Agonum tropicum Motschulsky, 1864
   Species: Agonum bicolor (Dejean, 1828)
   Species: Agonum muelleri (Herbst, 1784)
   Species: Agonum piceolum (LeConte, 1879)
   Species: Agonum anchomenoides Randall, 1838
   Species: Agonum canadense Goulet, 1969
   Species: Agonum consimile (Gyllenhal, 1810)
   Species: Agonum aeruginosum Dejean, 1828
   Species: Agonum affine Kirby, 1837
   Species: Agonum albicrus Dejean, 1828
   Species: Agonum anthracinum Dejean, 1831

或者如果有亚种的话

Genus: Apotomus Illiger, 1807
   Species: Apotomus angusticollis G. Müller, 1943
   Species: Apotomus annulaticornis Péringuey, 1896
        Subspecies: Apotomus annulaticornis annulaticornis Péringueyy, 1896
        Subspecies: Apotomus annulaticornis perrieri Jeannel, 1946
   Species: Apotomus atripennis Motschulsky, 1858
   Species: Apotomus australis Castelnau, 1867
   Species: Apotomus chaudoirii Wollaston, 1860
   Species: Apotomus clypeonitens G. Müller, 1943
        Subspecies: Apotomus clypeonitens adanensis Jedlicka, 1961
        Subspecies: Apotomus clypeonitens clypeonitens G. Müller, 1943
        Subspecies: Apotomus clypeonitens heinzi Wrase, 1992
   Species: Apotomus fairmairei Jeannel, 1946
   Species: Apotomus flavescens Apetz, 1854

问题是,在第一个样本中应该有像这样炫耀的亚属

Genus: Agonum Bonelli, 1810
   Species: Agonum patinale Bates, 1882
   Species: Agonum scutiferum Bates, 1878
   Species: Agonum tropicum Motschulsky, 1864
     Subgenus: Agonum (Agonum) Bonelli, 1810
       Species: Agonum bicolor (Dejean, 1828)
       Species: Agonum muelleri (Herbst, 1784)
       Species: Agonum piceolum (LeConte, 1879)
     Subgenus: Agonum (Europhilus) Chaudoir, 1859
       Species: Agonum anchomenoides Randall, 1838
       Species: Agonum canadense Goulet, 1969
       Species: Agonum consimile (Gyllenhal, 1810)
     Subgenus: Agonum (Olisares) Motschulsky, 1865
       Species: Agonum aeruginosum Dejean, 1828
       Species: Agonum affine Kirby, 1837
       Species: Agonum albicrus Dejean, 1828
       Species: Agonum anthracinum Dejean, 1831

我一生都无法弄清楚查询以提取数据并将其插入到树中应有的位置。

在数据库中,我为每个分类单元 Genus、Subgenus、Species、Subspecies 以及属一、Family、Order 等所有分类单元都有一个表,它们都有一个 ID 即 genus_id 和一个名称 genus_name all以相同的格式。

这是整个查询(减去数据库连接)

`$sql2 = "SELECT * FROM Genus ORDER BY genus_name";`
`$res2 = mysqli_query($conn, $sql2);`

        while($g = mysqli_fetch_array($res2, MYSQLI_ASSOC))
          
             {      
                $genus_name = "".$g['genus_name']."";
                
                echo "<b>Genus: $genus_name<br></b>";
                
                    
                
                       $sql = "SELECT * FROM Species WHERE genus_name =  '$genus_name'";
                     $res = mysqli_query($conn, $sql);
                        
                       while($d = mysqli_fetch_array($res, MYSQLI_ASSOC))
        
                         {
                          $kingdom_name = "".$d['kingdom_name']."";
                          $phylum_name = "".$d['phylum_name']."";
                          $subphylum_name = "".$d['subphylum_name']."";
                          $class_name = "".$d['class_name']."";
                          $subclass_name = "".$d['subclass_name']."";
                          $infraclass_name = "".$d['infraclass_name']."";
                          $superorder_name = "".$d['superorder_name']."";
                          $order_name = "".$d['order_name']."";
                          $suborder_name = "".$d['suborder_name']."";
                          $family_name   = "".$d['family_name']."";
                          $subfamily_name    = "".$d['subfamily_name']."";
                          $tribe_name = "".$d['tribe_name']."";
                          $genus_name = "".$d['genus_name']."";
                          $subgenus_name = "".$d['subgenus_name']."";
                          $species_name = "".$d['species_name']."";
                          $subspecies_name = "".$d['subspecies_name']."";
                     
                           
                   
                            if($species_name != '')
                             {
                              echo "&nbsp;&nbsp;&nbsp;Species: $species_name<br>";
                             }
                            if($subspecies_name != '')
                             {
                              echo "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Subspecies: $subspecies_name<br>";
                             }
                         }
                   
             }     

任何的建议都受欢迎。

理想情况下,使用这种类型的东西,我喜欢将问题抽象到数据结构中。 第二步是将数据结构转化为输出,这是一个单独的问题。 使用这种数据,虽然可以使用数组,或者甚至不需要抽象问题,但最好有一个类似 DOM 的树,这样您就可以随时获取节点的父节点。 理想情况下,有一个节点类可以容纳也是节点的子节点。 虽然您可以使用 PHP 内置的 DOM 操作,但您也可以为此构建自己的类,因为它相对简单:

<?php

class TreeNode
{
    protected $depth,$type,$text,$children,$parent;
    public function __construct(string $type = 'root', string $text = '')
    {
        $this->type = $type;
        $this->text = $text;
        $this->depth = 0;
        $this->children = [];
    }
    public function setParent(TreeNode $parent)
    {
        $this->parent = $parent;
    }
    public function addChildNode(TreeNode $child)
    {
        $child->setParent($this);
        $child->setDepth($this->depth+1);
        $this->children[] = $child;
        return $child;
    }
    public function addChild(string $type, string $text)
    {
        return $this->addChildNode(new TreeNode($type,$text));
    }
    public function setDepth(int $depth)
    {
        $this->depth = $depth;
    }
    public function getDepth()
    {
         return $this->depth;
    }
    public function getText(){
        return $this->text;
    }
    public function getType()
    {
        return $this->type;
    }
    public function getChildren()
    {
        return $this->children;
    }
    public function getParent()
    {
        return $this->parent;
    }
    public function nodeHtml()
    {
        if($this->type === 'root'){ return ''; }
        return str_repeat('&nbsp;',$this->depth*4).$this->type.': '.htmlentities($this->text);
    }
    public function treeHtml()
    {
        $out = $this->nodeHTML();
        if($this->type !== 'root'){ $out .= '<br>'; }
        foreach($this->children as $child)
        {
            $out .= $child->treeHtml();
        }
        return $out;
    }
}

$root = new TreeNode();
$pointer = $root->addChild('Genus', 'Agonum Bonelli, 1810');
$pointer->addChild('Species', 'Agonum patinale Bates, 1882');
$pointer->addChild('Species', 'Agonum scutiferum Bates, 1878');
$pointer = $pointer->addChild('Species', 'Agonum tropicum Motschulsky, 1864');
$pointer = $pointer->addChild('Subgenus','Agonum (Agonum) Bonelli, 1810');
$pointer->addChild('Species','Agonum bicolor (Dejean, 1828)');
$pointer->addChild('Species','Agonum muelleri (Herbst, 1784)');
$pointer->addChild('Species','Agonum piceolum (LeConte, 1879)');
$pointer = $pointer->getParent();
$pointer = $pointer->addChild('Subgenus','Agonum (Europhilus) Chaudoir, 1859');
$pointer->addChild('Species','Agonum anchomenoides Randall, 1838');
$pointer->addChild('Species','Agonum canadense Goulet, 1969');
$pointer->addChild('Species','Agonum consimile (Gyllenhal, 1810)');
$pointer = $pointer->getParent();
$pointer = $pointer->addChild('Subgenus','Agonum (Olisares) Motschulsky, 1865');
$pointer->addChild('Species','Agonum aeruginosum Dejean, 1828');
$pointer->addChild('Species','Agonum affine Kirby, 1837');
$pointer->addChild('Species','Agonum albicrus Dejean, 1828');
$pointer->addChild('Species','Agonum anthracinum Dejean, 1831');
echo $root->treeHtml();

输出将是:

    Genus: Agonum Bonelli, 1810
        Species: Agonum patinale Bates, 1882
        Species: Agonum scutiferum Bates, 1878
        Species: Agonum tropicum Motschulsky, 1864
            Subgenus: Agonum (Agonum) Bonelli, 1810
                Species: Agonum bicolor (Dejean, 1828)
                Species: Agonum muelleri (Herbst, 1784)
                Species: Agonum piceolum (LeConte, 1879)
            Subgenus: Agonum (Europhilus) Chaudoir, 1859
                Species: Agonum anchomenoides Randall, 1838
                Species: Agonum canadense Goulet, 1969
                Species: Agonum consimile (Gyllenhal, 1810)
            Subgenus: Agonum (Olisares) Motschulsky, 1865
                Species: Agonum aeruginosum Dejean, 1828
                Species: Agonum affine Kirby, 1837
                Species: Agonum albicrus Dejean, 1828
                Species: Agonum anthracinum Dejean, 1831

它应该很容易修改以满足您的需求。 基本上循环应该看起来像这样:在任何循环之前将 $pointer 设置为根节点。 做你的外循环:

$pointer = $root->addChild('Genus', 'Agonum Bonelli, 1810');

如果有任何内部循环要做,则指针将已设置为刚刚插入的子级。 完成内部循环后,作为外部循环的最后一行,您将执行以下操作:

$pointer = $pointer->getParent();

任何嵌套都可以重复此逻辑,当您需要在树中插入更高的节点时,您只需要引用指针的父级即可。 您还可以存储对特定节点的引用,如果您需要乱序插入内容,该引用将被保留。

我相信你可以把它转移到你的循环中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM