尝试在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很容易修复。 只需列出具有正确类别的正确链接即可。
答案 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)
要遵循的一些原则:
while
或do while
构造。它们引入了无限循环的大风险,这可能会破坏您的应用程序或系统。在mysqli中使用while
循环的情况下,可以使用它们,但要小心。确保没有无限循环可以被激活。query
查询数据库。通过始终使用它们来养成习惯。它们非常重要,因为使用它们可以避免所谓的mysql injections。$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>
</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);
输出: