【问题标题】:Building an unordered list from multiple MySQL tables从多个 MySQL 表构建无序列表
【发布时间】:2015-01-04 00:11:51
【问题描述】:

我正在尝试构建一个菜单,其中包含存储在数据库中三个单独的表中的类别、子类别和三级类别,如下所示:

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 |
--------------------------------------

这些应该在一个看起来像这样的无序列表中返回

  • 类别 1
    • 子类别 1
      • 第三类 1
    • 子类别 2
      • 第三类 2
      • 第三类 3
  • 类别 2
    • 子类别 3
      • 第三类 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/>';

}

}

【问题讨论】:

  • 你尝试过什么吗?
  • 我会加入数据库以返回单个结果集(但按顺序),然​​后在一个专注于类别 ID/名称更改的循环中将其放入表中。
  • 我试图找出 JOIN 但根本没有得到任何结果,我尝试了多个查询但无法弄清楚。事情是……我主要是一名设计师,我的 PHP/MySQL 技能充其量是有限的,而且生疏。如果有人想写下必要的代码以使其正常工作,我会很长时间(并且通过研究所述代码能够理解如何为将来的需要执行此操作)
  • 您可以进行查询以获取第一级,并为它们中的每一个回显类别名称并查询第二级,对于这些第二级中的每一个,执行相同的操作:回显子类别并查询第三级。最后,对于每个第三级,呼应第三级。不是最优化的,但很简单。

标签: php html mysql web html-lists


【解决方案1】:

我将只使用一个简单的连接来获取所有父/子关系,并在代码中对顶级父级的输出进行排序(这在 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;
    }
}

【讨论】:

  • 谢谢,虽然我仍然不确定如何输出,但会尝试弄清楚:)
  • 更新了一个简单的 php 脚本来输出列表。由于这仅使用单个 SQL 查询,因此应该相当有效。如果调整一下来检查 id 的变化会更好,但我越来越懒了。
  • 谢谢!这是向前迈出的一大步。有一个小问题,在第二层和第三层,每个条目都放在一个单独的
      中,而不是一个单独的(应该有一个
        包含所有第二层条目,并且一个围绕所有第三层条目如果这是有道理的......)。试图找出原因。其他一切都很好:)
  • 对于每个层级更改,它都会生成一个新的无序列表。如果你愿意,我可以修改它以避免这种情况。给我几分钟。
  • 大成功!非常非常感谢你!现在只需要使用 CSS 进行样式设置即可,这让我感觉更舒服 :)
【解决方案2】:

这是目前的代码,但没有返回任何结果。

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

?>

【讨论】:

    【解决方案3】:

    所有查询都返回一维数据。但是你可以有这样的解决方法:

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

    【讨论】:

    • 感谢您的帮助。看看这是否能让我更进一步
    • 试过了,但没有返回结果。我能麻烦你发布一个包含数据库连接等的完整脚本,这样我就可以看到我在哪里搞砸了?
    • 如果你需要'包括数据库连接',那么首先,去那里:google.com/search?q=php+mysqli+basics
    • 我将添加一个 aswer 以获取现在的 while 代码,不提供任何回报
    • 在您的第一个 sn-p 中,您将 level 添加到数据库中还是 levelparent_id?我希望你能回答我这个老问题!
    猜你喜欢
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 2014-10-13
    • 2018-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    相关资源
    最近更新 更多