[英]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 " Species: $species_name<br>";
}
if($subspecies_name != '')
{
echo " 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(' ',$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.