将 PHP MYSQL 中的类别 Table 中的所有热门类别作为 Optgroup
Putting All Top Categories as Optgroup from Category Table in PHP MYSQL
我几乎无法将所有顶级类别放入 Optgroup,尝试了几种方法,从 Whosebug 中获取了很多参考资料,但未能按照我的要求实现。
参考了 here 并构建了我的嵌套类别:
function fetchCategoryTree($parent = 0, $spacing = '', $user_tree_array = '') {
global $conn;
if (!is_array($user_tree_array)) {
$user_tree_array = array();
}
$sql = "SELECT `id`, `name`, `parent_id` FROM `acct_categs` WHERE `parent_id` = '".$parent."' ORDER BY `name` ASC";
$query = $conn->Execute($sql);
if (count($query) > 0) {
$current_parent = '';
while ($row = $query->FetchRow()) {
$user_tree_array[] = array("catid" => $row['id'], "catname" => $spacing . $row['name']);
$user_tree_array = fetchCategoryTree($row['id'], $spacing . '- ', $user_tree_array);
}
}
return $user_tree_array;
}
function categoryoption(){
$categoryList = fetchCategoryTree();
$dropdown = '<select name="category_id">';
foreach($categoryList as $cl) {
$dropdown .= "\n<option value=\"".$cl["catid"]."\">".$cl["catname"]."</option>";
}
$dropdown .= "</select>";
return $dropdown;
}
echo categoryoption();
所以当我回应这个时,我得到以下下拉列表:
<select name="category_id">
<option value="91">Assets</option>
<option value="3">- Capital Assets</option>
<option value="23">- - Accum. Amort. -Furn. & Equip.</option>
<option value="25">- - Accum. Amort. -Vehicle</option>
<option value="22">- - Office Furniture & Equipment</option>
<option value="24">- - Vehicle</option>
<option value="1">- Current Assets</option>
<option value="15">- - Accounts Receivables</option>
<option value="16">- - Allowance for doubtful accounts</option>
<option value="13">- - Checking Account</option>
....</select>
我想要的是这样的,https://jsfiddle.net/sbnzp1wL/
<select name="category_id">
<optgroup label="Assets"></optgroup>
<optgroup label="Capital Assets"></optgroup>
<option value="23">- - Accum. Amort. -Furn. & Equip.</option>
<option value="25">- - Accum. Amort. -Vehicle</option>
<option value="22">- - Office Furniture & Equipment</option>
<option value="24">- - Vehicle</option>
<optgroup label="Current Assets"></optgroup>
<option value="15">- - Accounts Receivables</option>
<option value="16">- - Allowance for doubtful accounts</option>
<option value="13">- - Checking Account</option>
<option value="14">- - Petty Cash</option>
....</select>
我读到它在 Whosebug 中的嵌套查询中是不可能的,但我也从 here 中了解到它是可能的。
但是有了 link 的帮助,我的顶级类别列出了二级类别,二级类别列出了它的子类别。不知何故,我也没有达到我想要的。
我的 table 值是 here
终于按照我的需要让它工作了,如果有人需要它,我把它贴在这里...非常感谢@stj(答案被接受并投票)
$sql = "SELECT `id`, `name`, `parent_id` FROM `acct_categs` ORDER BY `name` ASC";
$query = $conn->Execute($sql);
// build a lookup array with all elements
$all = array();
$hasChildren = array();
while ($row = $query->FetchRow()) {
$all[$row["id"]] = $row;
$hasChildren[$row["parent_id"]] = true;
}
// recursive processing function
function process($rows, $hasChildren, $parentId, $level = 0) {
foreach ($rows as $id => $row) {
if ($row["parent_id"] === $parentId) {
// this is the element we are looking for
$pad = str_repeat(" ", $level);
if (isset($hasChildren[$id])) {
// the element has children
$line = "\n<optgroup label=\"{$row["name"]}\"></optgroup>";
//$line = $pad . $row["id"] . " - " . $row["name"] . " (has children)";
} else {
// the element does not have any children
$line = "\n<option value=\"{$row["id"]}\">{$row["name"]}</option>";
//$line = $pad . $row["id"] . " - " . $row["name"] . " (no children)";
}
// print it
print $line . "\n";
// finally process the children
if (isset($hasChildren[$id])) {
process($rows, $hasChildren, $id, $level + 1);
}
}
}
}
echo '<select name="category_id">';
// start processing
$print = process($all, $hasChildren, "0");
echo $print;
echo '</select>';
获取所有带有 parent_id = 0
的猫,然后循环它,并得到 child。 Parent <optgroup></optgroup>
中的类别 wrapp,<option></option>
中的 child。
尝试将 parent ID 检查添加到您的 $categoryList
循环中:
function fetchCategoryTree($parent = 0, $spacing = '', $user_tree_array = '') {
global $conn;
if (!is_array($user_tree_array)) {
$user_tree_array = array();
}
$sql = "SELECT `id`, `name`, `parent_id` FROM `acct_categs` WHERE `parent_id` = '".$parent."' ORDER BY `name` ASC";
$query = $conn->Execute($sql);
if (count($query) > 0) {
$current_parent = '';
while ($row = $query->FetchRow()) {
$user_tree_array[] = array("catid" => $row['id'], "catname" => $spacing . $row['name'], "parentid" => $row['parent_id']);
$user_tree_array = fetchCategoryTree($row['id'], $spacing . '- ', $user_tree_array);
}
}
return $user_tree_array;
}
function categoryoption(){
$categoryList = fetchCategoryTree();
$dropdown = '<select name="category_id">';
foreach($categoryList as $cl) {
if ($c1["parentid"] == '0') {
$dropdown .= "\n<optgroup label=\"".$cl["catname"]."\"></optgroup>";
} else {
$dropdown .= "\n<option value=\"".$cl["catid"]."\">".$cl["catname"]."</option>";
}
}
$dropdown .= "</select>";
return $dropdown;
}
echo categoryoption();
您可能正在寻找的是呈现嵌套数据的深度优先递归。
我建议使用单个查询从数据库中查询所有值并在 PHP 中处理它们。这样可以避免发出大量单独的数据库查询(每个元素一个)。
查询完所有相关行后,您可以递归地遍历它们 PHP。
这是一些可以做到这一点的代码。
$sql = "SELECT `id`, `name`, `parent_id` FROM `acct_categs` ORDER BY `name` ASC";
$query = $conn->Execute($sql);
// build a lookup array with all elements
$all = array();
$hasChildren = array();
while ($row = $query->FetchRow()) {
$all[$row["id"]] = $row;
$hasChildren[$row["parent_id"]] = true;
}
// recursive processing function
function process($rows, $hasChildren, $parentId, $level = 0) {
foreach ($rows as $id => $row) {
if ($row["parent_id"] === $parentId) {
// this is the element we are looking for
$pad = str_repeat(" ", $level);
if (isset($hasChildren[$id])) {
// the element has children
$line = $pad . $row["id"] . " - " . $row["name"] . " (has children)";
}
else {
// the element does not have any children
$line = $pad . $row["id"] . " - " . $row["name"] . " (no children)";
}
// print it
print $line . "\n";
// finally process the children
if (isset($hasChildren[$id])) {
process($rows, $hasChildren, $id, $level + 1);
}
}
}
}
// start processing
process($all, $hasChildren, 0);
请注意,它不会打印嵌套的 optgroup。原因是我不确定 optgroups 应该去哪里。我认为 optgroup 元素不应该嵌套。但是,如果您真的想这样做,请继续。
此外,您可能需要根据需要调整填充 $line
的代码部分。
我喜欢一次查询所有值并使用合并对它们进行排序。这是我用过的最简单的选项。
<label>Category<br>
<select name="category_id">
<option value="0"> -- Choose Category -- </option>
<?
//All Categories
$sql = "SELECT id, parent_id, name FROM acct_categs ORDER BY COALESCE((SELECT NULLIF(parent_id,0)), id), NULLIF(parent_id,0)";
$catQuery = $conn->Execute($sql);
if($catQuery->num_rows > 0) {
while($cat = $catQuery->fetch_object()){
if($cat->parentId == 0){
echo '<optgroup label="'.$cat->title.'"></optgoup>';
} else {
echo '<option value="'.$cat->id.'">'.$cat->title.'</option>';
}
}
}
?>
</select>
</label>
我几乎无法将所有顶级类别放入 Optgroup,尝试了几种方法,从 Whosebug 中获取了很多参考资料,但未能按照我的要求实现。
参考了 here 并构建了我的嵌套类别:
function fetchCategoryTree($parent = 0, $spacing = '', $user_tree_array = '') {
global $conn;
if (!is_array($user_tree_array)) {
$user_tree_array = array();
}
$sql = "SELECT `id`, `name`, `parent_id` FROM `acct_categs` WHERE `parent_id` = '".$parent."' ORDER BY `name` ASC";
$query = $conn->Execute($sql);
if (count($query) > 0) {
$current_parent = '';
while ($row = $query->FetchRow()) {
$user_tree_array[] = array("catid" => $row['id'], "catname" => $spacing . $row['name']);
$user_tree_array = fetchCategoryTree($row['id'], $spacing . '- ', $user_tree_array);
}
}
return $user_tree_array;
}
function categoryoption(){
$categoryList = fetchCategoryTree();
$dropdown = '<select name="category_id">';
foreach($categoryList as $cl) {
$dropdown .= "\n<option value=\"".$cl["catid"]."\">".$cl["catname"]."</option>";
}
$dropdown .= "</select>";
return $dropdown;
}
echo categoryoption();
所以当我回应这个时,我得到以下下拉列表:
<select name="category_id">
<option value="91">Assets</option>
<option value="3">- Capital Assets</option>
<option value="23">- - Accum. Amort. -Furn. & Equip.</option>
<option value="25">- - Accum. Amort. -Vehicle</option>
<option value="22">- - Office Furniture & Equipment</option>
<option value="24">- - Vehicle</option>
<option value="1">- Current Assets</option>
<option value="15">- - Accounts Receivables</option>
<option value="16">- - Allowance for doubtful accounts</option>
<option value="13">- - Checking Account</option>
....</select>
我想要的是这样的,https://jsfiddle.net/sbnzp1wL/
<select name="category_id">
<optgroup label="Assets"></optgroup>
<optgroup label="Capital Assets"></optgroup>
<option value="23">- - Accum. Amort. -Furn. & Equip.</option>
<option value="25">- - Accum. Amort. -Vehicle</option>
<option value="22">- - Office Furniture & Equipment</option>
<option value="24">- - Vehicle</option>
<optgroup label="Current Assets"></optgroup>
<option value="15">- - Accounts Receivables</option>
<option value="16">- - Allowance for doubtful accounts</option>
<option value="13">- - Checking Account</option>
<option value="14">- - Petty Cash</option>
....</select>
我读到它在 Whosebug 中的嵌套查询中是不可能的,但我也从 here 中了解到它是可能的。
但是有了 link 的帮助,我的顶级类别列出了二级类别,二级类别列出了它的子类别。不知何故,我也没有达到我想要的。
我的 table 值是 here
终于按照我的需要让它工作了,如果有人需要它,我把它贴在这里...非常感谢@stj(答案被接受并投票)
$sql = "SELECT `id`, `name`, `parent_id` FROM `acct_categs` ORDER BY `name` ASC";
$query = $conn->Execute($sql);
// build a lookup array with all elements
$all = array();
$hasChildren = array();
while ($row = $query->FetchRow()) {
$all[$row["id"]] = $row;
$hasChildren[$row["parent_id"]] = true;
}
// recursive processing function
function process($rows, $hasChildren, $parentId, $level = 0) {
foreach ($rows as $id => $row) {
if ($row["parent_id"] === $parentId) {
// this is the element we are looking for
$pad = str_repeat(" ", $level);
if (isset($hasChildren[$id])) {
// the element has children
$line = "\n<optgroup label=\"{$row["name"]}\"></optgroup>";
//$line = $pad . $row["id"] . " - " . $row["name"] . " (has children)";
} else {
// the element does not have any children
$line = "\n<option value=\"{$row["id"]}\">{$row["name"]}</option>";
//$line = $pad . $row["id"] . " - " . $row["name"] . " (no children)";
}
// print it
print $line . "\n";
// finally process the children
if (isset($hasChildren[$id])) {
process($rows, $hasChildren, $id, $level + 1);
}
}
}
}
echo '<select name="category_id">';
// start processing
$print = process($all, $hasChildren, "0");
echo $print;
echo '</select>';
获取所有带有 parent_id = 0
的猫,然后循环它,并得到 child。 Parent <optgroup></optgroup>
中的类别 wrapp,<option></option>
中的 child。
尝试将 parent ID 检查添加到您的 $categoryList
循环中:
function fetchCategoryTree($parent = 0, $spacing = '', $user_tree_array = '') {
global $conn;
if (!is_array($user_tree_array)) {
$user_tree_array = array();
}
$sql = "SELECT `id`, `name`, `parent_id` FROM `acct_categs` WHERE `parent_id` = '".$parent."' ORDER BY `name` ASC";
$query = $conn->Execute($sql);
if (count($query) > 0) {
$current_parent = '';
while ($row = $query->FetchRow()) {
$user_tree_array[] = array("catid" => $row['id'], "catname" => $spacing . $row['name'], "parentid" => $row['parent_id']);
$user_tree_array = fetchCategoryTree($row['id'], $spacing . '- ', $user_tree_array);
}
}
return $user_tree_array;
}
function categoryoption(){
$categoryList = fetchCategoryTree();
$dropdown = '<select name="category_id">';
foreach($categoryList as $cl) {
if ($c1["parentid"] == '0') {
$dropdown .= "\n<optgroup label=\"".$cl["catname"]."\"></optgroup>";
} else {
$dropdown .= "\n<option value=\"".$cl["catid"]."\">".$cl["catname"]."</option>";
}
}
$dropdown .= "</select>";
return $dropdown;
}
echo categoryoption();
您可能正在寻找的是呈现嵌套数据的深度优先递归。
我建议使用单个查询从数据库中查询所有值并在 PHP 中处理它们。这样可以避免发出大量单独的数据库查询(每个元素一个)。
查询完所有相关行后,您可以递归地遍历它们 PHP。 这是一些可以做到这一点的代码。
$sql = "SELECT `id`, `name`, `parent_id` FROM `acct_categs` ORDER BY `name` ASC";
$query = $conn->Execute($sql);
// build a lookup array with all elements
$all = array();
$hasChildren = array();
while ($row = $query->FetchRow()) {
$all[$row["id"]] = $row;
$hasChildren[$row["parent_id"]] = true;
}
// recursive processing function
function process($rows, $hasChildren, $parentId, $level = 0) {
foreach ($rows as $id => $row) {
if ($row["parent_id"] === $parentId) {
// this is the element we are looking for
$pad = str_repeat(" ", $level);
if (isset($hasChildren[$id])) {
// the element has children
$line = $pad . $row["id"] . " - " . $row["name"] . " (has children)";
}
else {
// the element does not have any children
$line = $pad . $row["id"] . " - " . $row["name"] . " (no children)";
}
// print it
print $line . "\n";
// finally process the children
if (isset($hasChildren[$id])) {
process($rows, $hasChildren, $id, $level + 1);
}
}
}
}
// start processing
process($all, $hasChildren, 0);
请注意,它不会打印嵌套的 optgroup。原因是我不确定 optgroups 应该去哪里。我认为 optgroup 元素不应该嵌套。但是,如果您真的想这样做,请继续。
此外,您可能需要根据需要调整填充 $line
的代码部分。
我喜欢一次查询所有值并使用合并对它们进行排序。这是我用过的最简单的选项。
<label>Category<br>
<select name="category_id">
<option value="0"> -- Choose Category -- </option>
<?
//All Categories
$sql = "SELECT id, parent_id, name FROM acct_categs ORDER BY COALESCE((SELECT NULLIF(parent_id,0)), id), NULLIF(parent_id,0)";
$catQuery = $conn->Execute($sql);
if($catQuery->num_rows > 0) {
while($cat = $catQuery->fetch_object()){
if($cat->parentId == 0){
echo '<optgroup label="'.$cat->title.'"></optgoup>';
} else {
echo '<option value="'.$cat->id.'">'.$cat->title.'</option>';
}
}
}
?>
</select>
</label>