Я пытаюсь создать меню, заполненное категориями, подкатегориями и третичными категориями, которые хранятся в трех отдельных таблицах в базе данных следующим образом:
TABLE A
------------------------
| ID | name |
| 1 | Category 1 |
| 2 | Category 2 |
------------------------
TABLE B
------------------------------------
| ID | Parent_ID | name_b |
| 1 | 1 | Subcategory 1 |
| 2 | 1 | Subcategory 2 |
| 3 | 2 | Subcategory 3 |
------------------------------------
TABLE C
--------------------------------------
| ID | Parent_ID | name_c |
| 1 | 1 | Tertiarycategory 1 |
| 2 | 2 | Tertiarycategory 2 |
| 3 | 2 | Tertiarycategory 3 |
| 4 | 3 | Tertiarycategory 4 |
--------------------------------------
Они должны быть возвращены в неупорядоченном списке, выглядящем как
Я пару дней гуглял, пробуя разные вещи, но, похоже, не могу заставить их работать, поэтому очень буду признателен, если кто-то сможет взломать это для меня 🙂
Пробовал это, чтобы получить первый и второй уровни (без перечисления, просто нормальное эхо, пока я правильно понимаю запросы), но это не сработало вообще …
$query_select = "SELECT * FROM table_a";
$result_select = mysqli_query($link, $query_select) or die(mysql_error());
$rows = array();
while($menurow = mysqli_fetch_array($result_select))
$menurows[] = $menurow;
foreach($menurows as $menurow){
$ename = stripslashes($menurow['name']);
$eid = $menurow['id'];
echo $ename . '<br/>';
$query_select2 = "SELECT * FROM table_b WHERE parent_id = '$eid'";
$result_select2 = mysqli_query($link, $query_select2) or die(mysql_error());
$rows2 = array();
while($menurow2 = mysqli_fetch_array($result_select2))
$menurows2[] = $menurow2;
foreach($menurows2 as $menurow2){
$ename2 = stripslashes($menurow2['name_b']);
$eid2 = $menurow2['id'];
echo $ename2 . '<br/>';
}
}
Я бы просто использовал простое соединение, чтобы получить все родительские / дочерние отношения, и отсортировать вывод родителей верхнего уровня в коде, когда они меняются (это было бы легко в php).
SELECT name, name_b, name_c
FROM A
LEFT OUTER JOIN B
ON A.ID = B.Parent_ID
LEFT OUTER JOIN C
ON B.ID = C.Parent_ID
ORDER BY A.ID, B.ID, C.ID
РЕДАКТИРОВАТЬ
PHP скрипт для извлечения деталей из таблицы и построения неупорядоченных списков.
Это использует небольшой класс для вывода каждого неупорядоченного списка, закрывая его в деструкторе. Затем он создает экземпляр этого класса для каждого уровня неупорядоченного списка.
<?php
#------ database connections -------
define('MYSQLHOST','localhost');
define('MYSQLUSER','root');
define('MYSQLPASS','');
define('MYSQLDATABASE','tests');
$link = mysqli_connect(MYSQLHOST, MYSQLUSER, MYSQLPASS, MYSQLDATABASE);
$prev_name = '';
$prev_name_b = '';
$prev_name_c = '';
$query_select = "SELECT name, name_b, name_c
FROM A
LEFT OUTER JOIN B
ON A.ID = B.Parent_ID
LEFT OUTER JOIN C
ON B.ID = C.Parent_ID
ORDER BY A.ID, B.ID, C.ID";
$result_select = mysqli_query($link, $query_select) or die(mysql_error());
$rows = array();
while($menurow = mysqli_fetch_array($result_select))
{
if ($menurow['name'] != $prev_name)
{
if (isset($name_c_object)) unset($name_c_object);
if (isset($name_b_object)) unset($name_b_object);
if (isset($name_object)) unset($name_object);
$name_object = new ul(1);
$prev_name = $menurow['name'];
$name_object->li($prev_name);
}
if ($menurow['name_b'] != $prev_name_b)
{
if (isset($name_c_object)) unset($name_c_object);
if (isset($name_b_object)) unset($name_b_object);
$name_b_object = new ul(3);
$prev_name_b = $menurow['name_b'];
$name_b_object->li($prev_name_b);
if (isset($name_c_object)) unset($name_c_object);
$name_c_object = new ul(5);
}
$name_c_object->li($menurow['name_c']);
}
if (isset($name_c_object)) unset($name_c_object);
if (isset($name_b_object)) unset($name_b_object);
if (isset($name_object)) unset($name_object);
class ul
{
private $out_li = false;
private $num_tab = 0;
public function __CONSTRUCT($num_tab)
{
$this->num_tab = $num_tab;
echo str_repeat("\t", $this->num_tab)."<ul>\r\n";
}
public function __DESTRUCT()
{
if ($this->out_li) echo str_repeat("\t", $this->num_tab)."\t</li>\r\n";
echo str_repeat("\t", $this->num_tab)."</ul>\r\n";
}
public function li($li)
{
if ($this->out_li) echo str_repeat("\t", $this->num_tab)."\t</li>\r\n";
echo str_repeat("\t", $this->num_tab)."\t<li>\r\n";
echo str_repeat("\t", $this->num_tab)."\t\t$li\r\n";
$this->out_li = true;
}
}
РЕДАКТИРОВАТЬ снова
Я переосмыслил и обдумал это: —
<?php
#------ database connections -------
define('MYSQLHOST','localhost');
define('MYSQLUSER','root');
define('MYSQLPASS','');
define('MYSQLDATABASE','tests');
$link = mysqli_connect(MYSQLHOST, MYSQLUSER, MYSQLPASS, MYSQLDATABASE);
$prev_id_a = 0;
$prev_id_b = 0;
$prev_id_c = 0;
$query_select = "SELECT name, name_b, name_c, A.ID AS aid, B.ID AS bid, C.ID AS cid
FROM A
LEFT OUTER JOIN B
ON A.ID = B.Parent_ID
LEFT OUTER JOIN C
ON B.ID = C.Parent_ID
ORDER BY A.ID, B.ID, C.ID";
$result_select = mysqli_query($link, $query_select) or die(mysql_error());
$rows = array();
$name_a_object = new ul(0);
while($menurow = mysqli_fetch_array($result_select))
{
if ($menurow['aid'] != $prev_id_a)
{
if (isset($name_c_object)) unset($name_c_object);
if (isset($name_b_object)) unset($name_b_object);
$name_a_object->li($menurow['name']);
$name_b_object = new ul(2);
$prev_id_a = $menurow['aid'];
}
if ($menurow['bid'] != $prev_id_b)
{
if (isset($name_c_object)) unset($name_c_object);
$name_b_object->li($menurow['name_b']);
$name_c_object = new ul(4);
$prev_id_b = $menurow['bid'];
}
$name_c_object->li($menurow['name_c']);
}
if (isset($name_c_object)) unset($name_c_object);
if (isset($name_b_object)) unset($name_b_object);
if (isset($name_a_object)) unset($name_a_object);
class ul
{
private $num_tab = 0;
private $li_output = false;
public function __CONSTRUCT($num_tab, $li=null)
{
$this->num_tab = $num_tab;
echo str_repeat("\t", $this->num_tab)."<ul>\r\n";
if ($li != null)
{
echo str_repeat("\t", $this->num_tab)."\t<li>\r\n";
echo str_repeat("\t", $this->num_tab)."\t\t$li\r\n";
}
}
public function __DESTRUCT()
{
if ($this->li_output)
{
echo str_repeat("\t", $this->num_tab)."\t</li>\r\n";
}
echo str_repeat("\t", $this->num_tab)."</ul>\r\n";
}
public function li($li)
{
if ($this->li_output)
{
echo str_repeat("\t", $this->num_tab)."\t</li>\r\n";
}
echo str_repeat("\t", $this->num_tab)."\t<li>\r\n";
echo str_repeat("\t", $this->num_tab)."\t\t$li\r\n";
$this->li_output = true;
}
}
Все запросы возвращают данные в одном измерении. Но вы можете обойти это так:
SELECT x.level,x.id,x.name
FROM
(
SELECT 1 as level, id as id, name as name
, id as id_1,-1 as id_2, -1 as id_3
FROM table_a
WHERE 1
UNION
SELECT 2 as level, id as id, name_b as name
, Parent_ID as id_1,id as id_2, -1 as id_3
FROM table_b
WHERE 1
UNION
SELECT 3 as level, c.id as id, c.name_c as name
, b.Parent_ID as id_1,b.id as id_2, c.id as id_3
FROM table_c c LEFT JOIN table_b b ON c.Parent_ID=b.id
WHERE 1
) x
WHERE 1
ORDER BY id_1,id_2,id_3
что должно вернуться
Level | Name
1 Category 1
2 Subcategory 1
3 Tertiarycategory 1
2 Subcategory 2
3 Tertiarycategory 2
3 Tertiarycategory 3
1 Category 2
2 Subcategory 3
3 Tertiarycategory 4
и код PHP это:
$r = $db->query($query);
$level = 0;
while($x=mysql_fetch_object($r))
{
while($level < $x->level)
{
echo '<ul>';
$level++;
}
while($level > $x->level)
{
echo '</ul>';
$level--;
}
echo '<li>'$x->ID.'#'.$x->name;
}
while($level-- > 0)
echo '</ul>';
редактировать: Или вместо того, чтобы оставить работу по сборке MySQL, давайте сделаем это просто внутри PHP
$r1 = $db->query("SELECT * FROM table_a order by ID");
$r2 = $db->query("SELECT * FROM table_b order by Parent_ID");
$r3 = $db->query("SELECT table_c.*
FROM table_c
LEFT JOIN table_b ON table_c.Parent_ID=table_b.ID
order by table_b.Parent_ID");
$e1 = mysql_fetch_object($r1);
$e2 = mysql_fetch_object($r2);
$e3 = mysql_fetch_object($r3);
echo "<ul>";
while($e1)
{
echo "<li>".htmlentities($e1->name);
if($e2 && $e2->Parent_ID==$e1->ID)
{
echo "<ul>";
while($e2 && $e2->Parent_ID==$e1->ID)
{
echo "<li>".htmlentities($e2->name_b);
if($e3 && $e3->Parent_ID==$e2->ID)
{
echo "<ul>";
while($e3 && $e3->Parent_ID==$e2->ID)
{
echo "<li>".htmlentities($e3->name_3);
$e3 = mysql_fetch_object($r3);
}
echo "</ul>";
}
$e2 = mysql_fetch_object($r2);
}
echo "</ul>";
}
$e1 = mysql_fetch_object($r1);
}
echo "</ul>";
Это код в настоящее время, но результаты не возвращаются.
<?php
$host = "localhost"; //server
$db = "xx"; //database name
$user = "xx"; //dabases user name
$pwd = "xx"; //password
//connecting to server and creating link to database
$dblink = mysqli_connect($host, $user, $pwd, $db);
$r1 = $dblink->query("SELECT * FROM auction_a_categories order by ID");
$r2 = $dblink->query("SELECT * FROM auction_b_categories order by Parent_ID");
$r3 = $dblink->query("SELECT auction_c_categories.*
FROM auction_c_categories
LEFT JOIN auction_b_categories ON auction_c_categories.Parent_ID=auction_b_categories.ID
order by auction_b_categories.Parent_ID");
$e1 = mysql_fetch_object($r1);
$e2 = mysql_fetch_object($r2);
$e3 = mysql_fetch_object($r3);
echo "<ul>";
while($e1)
{
echo "<li>".htmlentities($e1->name);
if($e2 && $e2->Parent_ID==$e1->ID)
{
echo "<ul>";
while($e2 && $e2->Parent_ID==$e1->ID)
{
echo "<li>".htmlentities($e2->name_b);
if($e3 && $e3->Parent_ID==$e2->ID)
{
echo "<ul>";
while($e3 && $e3->Parent_ID==$e2->ID)
{
echo "<li>".htmlentities($e3->name_3);
$e3 = mysql_fetch_object($r3);
}
echo "</ul>";
}
$e2 = mysql_fetch_object($r2);
}
echo "</ul>";
}
$e1 = mysql_fetch_object($r1);
}
echo "</ul>";
?>