optgroup标签重复问题:同类别产品无法归入同一optgroup分组
问题解决:避免重复创建optgroup分组
当前代码能实现按类别分组,但每个产品都会生成独立的optgroup,导致同一类别被重复创建。正确的逻辑应该是同一类别下的所有产品归到同一个optgroup中。
问题根源
原代码在遍历每个产品时,都会生成一对<optgroup>标签,所以同一类别的每个产品都会触发一次分组创建,造成重复。
优化方案
- 先按类别聚合数据:通过SQL JOIN一次性获取产品及其所属类别,避免循环内重复查询数据库,提升效率。
- 按类别分组存储:将查询结果整理为以类别为键的数组,方便后续遍历输出。
- 遍历分组输出:先输出类别对应的
optgroup,再在组内循环输出该类别下的所有产品选项。
修正后的代码
<select style="width: 25%;" name="item[]" id="item1" class="item browser-default custom-select-new"> <option value="" disabled selected>点击查看产品</option> <?php $conn_register = mysqli_connect('localhost', 'root', '', 'register'); $Comid = "27"; // 使用JOIN一次性获取产品及对应类别,同时按类别排序 $records = mysqli_query($conn_register, " SELECT cp.*, ap.category FROM customer_product cp JOIN addproducts ap ON cp.product = ap.name WHERE cp.customer = '$Comid' ORDER BY ap.category "); // 按类别分组存储产品 $productsByCategory = []; while ($data = mysqli_fetch_array($records)) { $category = $data['category']; if (!isset($productsByCategory[$category])) { $productsByCategory[$category] = []; } $productsByCategory[$category][] = $data; } // 遍历每个类别,输出optgroup和对应的选项 foreach ($productsByCategory as $category => $products) { echo '<optgroup label="' . htmlspecialchars($category) . '">'; foreach ($products as $product) { echo '<option value="' . htmlspecialchars($product['product']) . '" data-new_price_rate="' . htmlspecialchars($product['new_total_rate']) . '" data-description="' . htmlspecialchars($product['description']) . '" data-tax="' . htmlspecialchars($product['tax']) . '" data-PriceRate_NoDiscount="' . htmlspecialchars($product['new_price_rate']) . '">' . htmlspecialchars($product['product']) . '</option>'; } echo '</optgroup>'; } ?> </select>
额外优化点
- 使用
htmlspecialchars()转义输出内容,避免XSS安全问题。 - 用JOIN替代循环内的多次查询,减少数据库交互次数,提升性能。
- 建议使用预处理语句(Prepared Statements)处理SQL查询,防止SQL注入风险,示例如下:
// 预处理语句示例 $stmt = $conn_register->prepare(" SELECT cp.*, ap.category FROM customer_product cp JOIN addproducts ap ON cp.product = ap.name WHERE cp.customer = ? ORDER BY ap.category "); $stmt->bind_param("s", $Comid); $stmt->execute(); $records = $stmt->get_result(); // 后续处理逻辑同上
内容的提问来源于stack exchange,提问作者Pierre
相关产品推荐
相关产品推荐

