大概有五、六、七、八、九年没有使用PHP了, 这两天突然被一个跨站点的同仁问了一个PHP的问题,据描述这个问题已经折磨他三天了。
问题厘清
他的问题是: “PHP里面调用MySQL 查询的问题, 在Windows执行正常,但是放到Linux下就有问题了”。
收到这个问题描述, 我的第一反应是有可能是PHP或者是MySQL模块的版本原因,于是我回复如下:
” 我这边猜想有可能是PHP 的 MySQL版本的原因,
因为PHP的MySQL模块升级后, SQL语法上有一些差异“。
所以我让他查看一下PHP的相关版本,可以他对PHP不熟悉,在Linux下也不知道如何查看PHP相关版本。
于是我让他共享桌面,才完整的看清了整个问题的全貌。
他的环境和功能是:
- 在浏览器中输入某些条件后查询MySQL数据库的某张表
- 有两个php文件,一个输入查询条件,一个显示查询结果
- 服务器使用的是Apache
真正的问题是:
在第一个页面不管输入什么条件,都会把该表中所有的数据查询出来。看上去后面的Where子句没有任何结果。
问题探索
应用的环境
从以上的观察来看, 我更进一步相信有可能是版本的原因, 于是我让他查看PHP相关的配置。首先需要解决的问题是在Linux中找到Apache和PHP的安装目录,查找方式是通过whereis命令, 比如查找php相关的目录:
whereis php
。
接下来是查看PHP的相关配置,我首先提供给的方式是:
- 在apache 的htdocs目录(或子目录)下创建一个phpinfo.php的文件,该文件的内容很简单:
<?php
phpinfo();
?>
- 添加完成后在浏览器输入 http://xxxx/php.info.php 之后就会显示PHP的版本、环境变量以及安装模块等配置信息。
查看PHP的配置信息 ,在Windows下也可以直接查看php.ini的文件内容, 如果只是需要获取PHP版本,也可以在命令行输入:
php -version
进行查看。
从查看的版本结果看, 在Windows和Linux下的版本的确不一致, 一个是PHP 5另外一个是PHP 7。是否真是版本原因导致的呢?
代码分析
从以上的分析看, 原因出现在SQL的执行上,很有可能是MySQL模块的版本原因, 于是就需要查看源码, 源码倒也简单,这里简化一下两个页面的代码:
- input.php, 输入查询条件页面
<html>
<head>
<title>Query</title>
</head>
<body>
<form action="result.php" method="Post">
Name:
<input type="Text" name="name">
<input type="Submit"><br>
</form>
</body>
</html>
- result.php 执行查询并显示查询结果页面
<html>
<head>
<title>Result</title>
</head>
<body>
<?
$NAME=$_REQUEST["name"];
?>
<?php
$conn =mysqli_connect("localhost","root","123456","oscar999");
$sql_query = "SELECT userid,name,sex FROM user where name like '$NAME%'";
$result = $conn->query($sql_query);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo "id: " . $row["userid"]. " - Name: " . $row["name"]. " " . $row["sex"]. "<br>";
}
} else {
echo "No result";
}
$conn->close();
?>
</body>
</html>
对以上代码说明如下:
$_REQUEST["name"];
通过$_REQUEST获取请求参数- SQL 语句很简单,where 子句中属性Like 一个参数。
解决思路
根据以上代码,首先的解决思路是:是不是因为版本等原因,SQL不能正确执行呢?
验证方式是把SQL 中where 的变量参数换成常量, 发现是正常的,所以MySQL查询是没有问题的。
既然SQL语句没有问题,那是不是因为前端的参数没有正确传递呢?
通过echo 打印传递的参数,
echo $NAME;
在浏览器报变量未定义的错误。
Notice: Undefined variable: NAME in
于是,问题定位了, 因为参数没有正确的传递, Where子句没有生效,所以每次都会将所有的数据找出来。
在回头细看代码,Oh My God,在获取参数的地方少了一个 php语言的标签。也就是在以下代码:
<?
$NAME=$_REQUEST["name"];
?>
<?
后面少了一个 php,正确的形式应该是:
<?php
$NAME=$_REQUEST["name"];
?>
总结
这个问题应该属于一个低级问题,导致的原因很大部分是因为粗心。但是出现问题的时候,处理起来却又是非常耗时的。特别是如何结合了一些假象,处理起来就更容易被误导。比如:
- 那个环境可以,这个环境不可以
- 以前是正常的,现在有问题
另外,这个问题出现不易发现的原因是没有任何错误出现,类似这里不是显示不出数据,而是把数据全部显示出来。
在实际开发中,除了养成细心的编程习惯外,也可以借助一些IDE开发工具提早发现这些错误。