PHP中MySQL UNION DISTINCT查询页面空白问题求助
问题分析与修复方案
核心问题点
- SQL语法错误与注入风险:直接将
$_GET['category']拼入SQL时,用反引号包裹变量是错误的——反引号仅用于标识表/字段名,字符串值需用单引号;且直接拼接用户输入会引发SQL注入,同时语法错误导致查询失败,$conn->query($sql)返回false,后续调用$result->num_rows触发“Trying to get property of non-object”错误。 - 结果字段匹配错误:UNION查询中每个子查询都将字段别名成
temp,但循环输出时试图读取sw_category1/sw_category2等原字段名,这些字段在结果集中不存在,导致即使查询成功也输出空白。 - 缺失查询错误处理:未判断查询是否执行成功,失败时直接进入错误逻辑,甚至因错误被屏蔽显示空白。
修复后的完整代码
<?php // 处理GET参数,避免未传参报错 $category = $_GET['category'] ?? ''; if(empty($category)) { echo "请传入category参数"; exit; } $servername = "localhost"; $username = "test"; $password = "****"; $dbname = "test"; $conn = new mysqli($servername, $username, $password, $dbname); if ($conn->connect_error) { die("Connection failed: " . $conn->connect_error); } // 优化后的简洁SQL,避免重复逻辑 $sql = "SELECT DISTINCT temp FROM ( SELECT sw_category1 AS temp FROM products UNION ALL SELECT sw_category2 AS temp FROM products UNION ALL SELECT sw_category3 AS temp FROM products UNION ALL SELECT sw_category4 AS temp FROM products ) AS all_categories WHERE temp = ?"; // 使用预处理语句,彻底避免SQL注入 $stmt = $conn->prepare($sql); $stmt->bind_param("s", $category); $stmt->execute(); $result = $stmt->get_result(); if ($result && $result->num_rows > 0) { while($row = $result->fetch_assoc()) { // 输出结果集中实际存在的temp字段 echo $row["temp"] . " "; } } else { echo "0 results"; } // 关闭资源 $stmt->close(); $conn->close(); ?>
关键修改说明
- 参数安全:用
$_GET['category'] ?? ''处理未传参场景,通过mysqli预处理语句prepare+bind_param避免SQL注入,同时修正原SQL的语法错误。 - 字段匹配:循环输出时读取查询结果中实际存在的
temp字段,确保内容能正常显示。 - 逻辑优化:将原重复的UNION查询简化为子查询+UNION ALL,提升查询效率。
- 错误防护:增加
$result有效性判断,避免查询失败时调用非对象属性。
内容的提问来源于stack exchange,提问作者Thorsverd
相关产品推荐
相关产品推荐

