在另一个while循环中使用while循环的结果

时间:2018-07-21 20:11:59

标签: php while-loop web

尝试在while循环内创建while循环时遇到了很大的麻烦。 第一个while循环应该输出类别。 第二个while循环应该输出与类别关联的链接。链接信息在链接表中,类别信息在类别表中。 我正在尝试对category.ID上的links.catID进行联接。

链接表:
    id链接网址 catID 类型

类别表:
     id 猫类型

links.catID应该等于int中的category.id。 然后category.cat将输出类别的名称。

我的代码是:

require 'db/connect.php';
$sql = "SELECT * FROM category";
$results = $db->query($sql);
echo "<p class='post-footer align-left'><span class='pageName'><span 
class='style3'>Links</span></span></p>";
    if($results->num_rows){
        while($row = $results->fetch_object()){
        echo "<table width='507' border='1'>";
        echo " <p class='post-footer align-left'><span class='pageName'><span class='style3'>{$row->cat}</span></span></p>";
        $sql1 = "SELECT links.url, links.links, links.catID FROM links INNER JOIN category on category.id WHERE category.id = links.catID";
        $results1 = $db->query($sql1);
            if ($results1->num_rows > 0) {
                while($row1 = $results1->fetch_object()){
                    echo "<th><span class='pageName'><span class='style3'>{$row1->links}</span></span></th>";
                }
            }
        }
    }

请对我好一点,我经验很少,上面很可能表明了这一点。我已经坚持了一段时间,只是想不通。我真的很感谢别人的帮助。

我想我已经在上面正确解释了:)

不用担心PHP的CSS。 CSS很容易修复。 只需列出具有正确类别的正确链接即可。

enter image description here

enter image description here

3 个答案:

答案 0 :(得分:0)

原始问题下的评论表明:

  

问题在于,它填充了数据库中每个类别下的所有链接。

您的问题来自于嵌套查询是静态字符串的事实。

在此查询中:

$sql1 = "SELECT links.url, links.links, links.catID FROM links INNER JOIN category on category.id WHERE category.id = links.catID";

没有变量。因此,无论您当前在while循环中评估哪个类别,您似乎都可能会获得 all 类别链接。我假设您想做这样的事情?

$sql1 = "SELECT links.url, links.links, links.catID FROM links INNER JOIN category on category.id WHERE category.id = links.catID AND category.id = {$row->id}";

此外,请记住,您的整体方法效率低下。几乎每次您为while循环的每次迭代调用查询 时,效率低下。理想情况下,您将使用一组适当的JOIN在第一个查询中拉回所有这些数据,然后在while循环中对其进行过滤。

答案 1 :(得分:0)

作为我的第一个答案的后续,下面的示例显示了如何使用单个查询来执行此操作。恕我直言,您应该始终选择这种方法。如果您只有少数几个类别需要深入,那么如果您坚持使用“查询嵌套内部循环”方法,则可能不会浪费很多性能。但是,如果您有相当多的类别,则以下方法应该会更加有效:

require 'db/connect.php';
$sql = "
    SELECT
        category.id
        , links.links
    FROM
        category
    LEFT JOIN
        links ON links.catID = category.id
    ORDER BY
        category.id ASC
        -- this ORDER BY is critical, it ensures that all of the
        -- records will be lumped by category
";
// (yes, this query will create multiple rows for every category, but that's OK,
// we're going to deal with that in the while() loop
$results = $db->query($sql);
echo "<p class='post-footer align-left'><span class='pageName'><span class='style3'>Links</span></span></p>";
if($results->num_rows){
    $previousId = '';
    while($row = $results->fetch_object()){
        $currentId = $row->id;
        if ($currentId !== $previousId) {
            // we only show the wrapper <table>, and the category header, if we've encountered a new
            // batch of rows which signifies that a new category is being processed
            echo "<table width='507' border='1'>";
            echo " <p class='post-footer align-left'><span class='pageName'><span class='style3'>{$row->cat}</span></span></p>";
        }
        echo "<th><span class='pageName'><span class='style3'>{$row->links}</span></span></th>";
        if ($currentId !== $previousId and $previousId !== '') {
            echo "</table>";  // this wasn't in your original code, but I assume it should be here
        }
        $previousId = $currentId;
    }
}
echo "</table>";

答案 2 :(得分:0)

要遵循的一些原则:

  • 避免编写其中包含html标记的php代码。
  • 请勿将获取数据库数据的php代码与html代码混合使用。在我的代码中,您会注意到我仅在网页的上方获取和处理了数据库数据。因此与html代码完全分开。在html代码中,我仅使用数组。为什么这很重要?因为,例如,如果Web设计人员应该自定义页面的设计,则他应该能够更改html代码,而不必(根据您的代码)被迫学习任何数据库访问命令。另一个原因是,在某些时候,您可能希望将数据访问代码与html代码分开。您只能这样做而不混合它们。因此,简而言之,HTML代码不应进行任何处理,而只能进行读取操作(从数组,从变量)。
  • 通常,避免使用whiledo while构造。它们引入了无限循环的大风险,这可能会破坏您的应用程序或系统。在mysqli中使用while循环的情况下,可以使用它们,但要小心。确保没有无限循环可以被激活。
  • 将您的代码向数据库提出的每个请求视为一项昂贵的操作。例如,如果您要获取一个包含500个类别的列表,并且对于每个类别,您都向数据库发出新请求以获取相应的链接列表,那么您将“淹没”您的Web服务器和数据库。
  • 考虑应用prepared statements而不是直接使用query查询数据库。通过始终使用它们来养成习惯。它们非常重要,因为使用它们可以避免所谓的mysql injections
  • 考虑使用复数形式命名表格。像“类别”。并且不要犹豫,给出良好的易于理解的数据库/表/列名称。为它们使用形式“ this_is_the_name”(下划线和小字符分隔)。在php中,将“ camelCase”语法用于php变量/函数/方法名称。像$mysqlConnection。 html控件的ID也应为camelCase:“ thisIsAnInputId”。而CSS类是这样的:“ this-is-a-div-class”。
  • 编写echo '<table width="507" border="1">';。看起来更好,不是吗?我几乎在所有地方都使用单引号,而不是双引号。在极少数情况下,我必须用反斜杠转义单引号字符,例如:echo 'I don\'t know';

一些不错的资源:


index.php:

<?php
require 'db/connect.php';

/*
 * The SQL statement. The external values are passed directly into it.
 * Therefore, the code is open to SQL injections. In order to avoid
 * them, an sql statement receiving external values should always be
 * prepared for execution.
 *
 * @link http://php.net/manual/en/mysqli.prepare.php
 */
$sql = 'SELECT
            c.id AS categoryId,
            c.cat,
            c.type,
            l.id AS linkId,
            l.url,
            l.links
        FROM links AS l
        INNER JOIN category AS c ON l.catID = c.id';

/*
 * Performs a query on the database.
 *
 * Returns FALSE on failure [<< and raises warnings, fatal errors, exceptions, etc >>].
 * For successful SELECT, SHOW, DESCRIBE or EXPLAIN queries mysqli_query() will return a
 * mysqli_result object. For other successful queries will return TRUE.
 *
 * @link https://secure.php.net/manual/en/mysqli.query.php
 */
$result = $db->query($sql);

/*
 * Fetch the data into an array like this:
 *
 * Array
 * (
 *     [0] => Array
 *         (
 *             [categoryId] => 1
 *             [cat] => Platforms
 *             [type] =>
 *             [linkId] => 1
 *             [url] => #
 *             [links] => CSI (Internet Explorer)
 *         )
 *
 *     [1] => Array
 *         (
 *             [categoryId] => 1
 *             [cat] => Platforms
 *             [type] =>
 *             [linkId] => 2
 *             [url] => #
 *             [links] => Customer view of Service Cloud
 *         )
 *
 *     [...] => [...]
 *
 *     [5] => Array
 *         (
 *             [categoryId] => 2
 *             [cat] => Engineering
 *             [type] =>
 *             [linkId] => 6
 *             [url] => #
 *             [links] => Check Returned OPTs
 *         )
 *
 *     [6] => Array
 *         (
 *             [categoryId] => 2
 *             [cat] => Engineering
 *             [type] =>
 *             [linkId] => 7
 *             [url] => #
 *             [links] => Eng Links
 *         )
 *
 *     [...] => [...]
 *
 * )
 */
$data = $result->fetch_all(MYSQLI_ASSOC);

/*
 * Iterate through the fetched data and save it into a new array, with
 * a structure suited for the required display. The new array looks like this:
 *
 * Array
 * (
 *     [1] => Array
 *         (
 *             [categoryName] => Platforms
 *             [categoryType] => red
 *             [links] => Array
 *                 (
 *                     [0] => Array
 *                         (
 *                             [1] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => CSI (Internet Explorer)
 *                                 )
 *
 *                             [2] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => CSI (Backup link - Don't have link)
 *                                 )
 *
 *                         )
 *
 *                     [1] => Array
 *                         (
 *                             [3] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => Customer view of Service Cloud
 *                                 )
 *
 *                             [4] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => Service Cloud
 *                                 )
 *
 *                         )
 *
 *                     [2] => Array
 *                         (
 *                             [5] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => Open to Suggestions
 *                                 )
 *
 *                         )
 *
 *                 )
 *
 *         )
 *
 *     [2] => Array
 *         (
 *             [categoryName] => Engineering
 *             [categoryType] => blue
 *             [links] => Array
 *                 (
 *                     [0] => Array
 *                         (
 *                             [6] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => Check Returned OPTs
 *                                 )
 *
 *                             [7] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => EMC Caller
 *                                 )
 *
 *                         )
 *
 *                     [1] => Array
 *                         (
 *                             [8] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => Eng Links
 *                                 )
 *
 *                             [9] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => Eng RCA Database
 *                                 )
 *
 *                         )
 *
 *                     [2] => Array
 *                         (
 *                             [10] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => OPT
 *                                 )
 *
 *                             [11] => Array
 *                                 (
 *                                     [linkUrl] => #
 *                                     [linkLinks] => Surge (Internet Explorer)
 *                                 )
 *
 *                         )
 *
 *                 )
 *
 *         )
 *
 * )
 */
$formattedData = [];

// The number of items (maximal 2) per each "links row" item.
$numberOfItemsPerLinksRow = 0;

// The index of a "links row" item.
$indexOfCurrentLinksRow = 0;

foreach ($data as $item) {
    // Extract category data.
    $categoryId = $item['categoryId'];
    $categoryName = $item['cat'];
    $categoryType = $item['type'];

    // Add a category item if not already exist, with the category id as the item's key.
    if (!array_key_exists($categoryId, $formattedData)) {
        $formattedData[$categoryId] = [];
        $formattedData[$categoryId]['categoryName'] = $categoryName;
        $formattedData[$categoryId]['categoryType'] = $categoryType;

        // In this category item add an array to hold the list of links items.
        $formattedData[$categoryId]['links'] = [];

        // Reset.
        $indexOfCurrentLinksRow = 0;

        // Reset.
        $numberOfItemsPerLinksRow = 0;
    }

    // Extract link data.
    $linkId = $item['linkId'];
    $linkUrl = $item['url'];
    $linkLinks = $item['links'];

    // Add the details of the link as an item in the "links row" item. Notice the link id as key.
    $formattedData[$categoryId]['links'][$indexOfCurrentLinksRow][$linkId] = [
        'linkUrl' => $linkUrl,
        'linkLinks' => $linkLinks,
    ];

    // Increment.
    $numberOfItemsPerLinksRow++;

    if ($numberOfItemsPerLinksRow % 2 === 0) {
        // Reset.
        $numberOfItemsPerLinksRow = 0;

        // Increment.
        $indexOfCurrentLinksRow++;
    }
}
?>
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
        <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=yes" />
        <meta charset="UTF-8" />
        <!-- The above 3 meta tags must come first in the head -->

        <title>Demo</title>

        <style type="text/css">
            body {
                margin: 0;
                padding: 20px;
                color: #333;
            }

            a {
                text-decoration: none;
            }

            .category {
                padding: 10px;
                margin-bottom: 10px;
                text-align: left;
                font-weight: 700;
                border: 1px solid #ccccff;
                background-color: #f3f8fd;
            }

            .links {
                width: 100%;
                border-spacing: 1px;
                border: 1px solid #fafafa;
            }

            .links td {
                width: 50%;
                padding: 10px;
                background-color: #fafafa;
            }

            .links td a {
                color: #0033ff;
                font-weight: 700;
                background-color: #f8f8f8;
            }

            .no-data {
                padding: 10px;
                margin-bottom: 10px;
                border: 1px solid #ddd;
                background-color: #f4f4f4;
            }
        </style>
    </head>
    <body>

        <h3>
            Categories
        </h3>

        <?php
        if ($formattedData) { // Data exists.
            foreach ($formattedData as $categoryId => $categoryItem) {
                ?>
                <p class="category">
                    <?php echo $categoryItem['categoryName']; ?>
                </p>

                <table class="links">
                    <?php
                    $links = $categoryItem['links'];

                    foreach ($links as $linksRow) {
                        ?>
                        <tr>
                            <?php
                            foreach ($linksRow as $linkId => $linkItem) {
                                ?>
                                <td>
                                    <a href="<?php echo $linkItem['linkUrl']; ?>">
                                        <?php echo $linkItem['linkLinks']; ?>
                                    </a>
                                </td>
                                <?php
                            }

                            // If there is no second link item in this "links row" item, then create an empty cell.
                            $numberOfItemsPerLinksRow = count($linksRow);
                            if ($numberOfItemsPerLinksRow === 1) {
                                ?>
                                <td>
                                    &nbsp;
                                </td>
                                <?php
                            }
                            ?>
                        </tr>
                        <?php
                    }
                    ?>
                </table>
                <?php
            }
        } else { // No data.
            ?>
            <p class="no-data">
                No data.
            </p>
            <?php
        }
        ?>

    </body>
</html>

db / connect.php:

别忘了更改数据库凭据。

<?php

// Db configs.
define('HOST', 'localhost');
define('PORT', 3306);
define('DATABASE', 'tests');
define('USERNAME', 'root');
define('PASSWORD', 'root');

/*
 * Enable internal report functions. This enables the exception handling,
 * e.g. mysqli will not throw PHP warnings anymore, but mysqli exceptions
 * (mysqli_sql_exception).
 *
 * MYSQLI_REPORT_ERROR: Report errors from mysqli function calls.
 * MYSQLI_REPORT_STRICT: Throw a mysqli_sql_exception for errors instead of warnings.
 *
 * @link http://php.net/manual/en/class.mysqli-driver.php
 * @link http://php.net/manual/en/mysqli-driver.report-mode.php
 * @link http://php.net/manual/en/mysqli.constants.php
 */
$mysqliDriver = new mysqli_driver();
$mysqliDriver->report_mode = (MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

/*
 * Create a new db connection.
 *
 * @see http://php.net/manual/en/mysqli.construct.php
 */
$db = new mysqli(HOST, USERNAME, PASSWORD, DATABASE, PORT);

表“类别”使用的定义和数据:

CREATE TABLE `category` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `cat` varchar(100) DEFAULT NULL,
  `type` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

INSERT INTO `category` (`id`, `cat`, `type`)
VALUES
    (1, 'Platforms', 'red'),
    (2, 'Engineering', 'blue');

用于表“链接”的定义和数据:

CREATE TABLE `links` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `links` varchar(100) DEFAULT NULL,
  `url` varchar(100) DEFAULT NULL,
  `catID` int(11) unsigned DEFAULT NULL,
  `type` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `catID` (`catID`),
  CONSTRAINT `links_ibfk_1` FOREIGN KEY (`catID`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8;

INSERT INTO `links` (`id`, `links`, `url`, `catID`, `type`)
VALUES
    (1, 'CSI (Internet Explorer)', '#', 1, NULL),
    (2, 'CSI (Backup link - Don\'t have link)', '#', 1, NULL),
    (3, 'Customer view of Service Cloud', '#', 1, NULL),
    (4, 'Service Cloud', '#', 1, NULL),
    (5, 'Open to Suggestions', '#', 1, NULL),
    (6, 'Check Returned OPTs', '#', 2, NULL),
    (7, 'EMC Caller', '#', 2, NULL),
    (8, 'Eng Links', '#', 2, NULL),
    (9, 'Eng RCA Database', '#', 2, NULL),
    (10, 'OPT', '#', 2, NULL),
    (11, 'Surge (Internet Explorer)', '#', 2, NULL);

输出:

Output image