我已将旧的MYSQL代码更改为PDO代码,但pdo代码无法正常运行。旧的mysql代码完美无缺。 PDO不显示结果。我找不到PDO中代码错误的位置。实际上它是APK的API
旧MYSQL
<?php
mysql_query("SET NAMES 'utf8'");
if(isset($_GET['cat_id'])){
$query="SELECT * FROM tbl_news_category c,tbl_news n WHERE c.cid=n.cat_id and c.cid='".$_GET['cat_id']."' ORDER BY n.id DESC";
$result = mysql_query($query);
}
else if(isset($_GET['latest_news'])){
$limit=$_GET['latest_news'];
$query="SELECT * FROM tbl_news_category c,tbl_news n WHERE c.cid=n.cat_id ORDER BY n.id DESC LIMIT $limit";
$result = mysql_query($query);
}
else if(isset($_GET['apps_details'])){
$query="SELECT * FROM tbl_settings WHERE id='1'";
$result = mysql_query($query);
}
else{
$query="SELECT * FROM tbl_news_category ORDER BY cid DESC";
$result = mysql_query($query);
}
$set = array();
$total_records = mysql_num_rows($result);
if($total_records >= 1){
while ($link = mysql_fetch_array($result, MYSQL_ASSOC)){
$set['NewsApp'][] = $link;
}
}
echo $val= str_replace('\\/', '/', json_encode($set));
?>
PDO
if(isset($_GET['cat_id'])){
$result=$con->prepare("SELECT * FROM tbl_news_category c,tbl_news n WHERE c.cid=n.cat_id and c.cid='".$_GET['cat_id']."' ORDER BY n.id DESC");
}
else if(isset($_GET['latest_news'])){
$limit=$_GET['latest_news'];
$result=$con->prepare("SELECT * FROM tbl_news_category c,tbl_news n WHERE c.cid=n.cat_id ORDER BY n.id DESC LIMIT $limit");
}
else if(isset($_GET['apps_details'])){
$result=$con->prepare("SELECT * FROM tbl_settings WHERE id='1'");
}
else{
$result=$con->prepare("SELECT * FROM tbl_news_category ORDER BY cid DESC");
}
$set = array();
$result->execute();
$total_records = $result->fetchColumn();
if($total_records >= 1){
while($link=$result->fetch(PDO::FETCH_ASSOC)){
$set['NewsApp'][] = $link;
}
}
echo $val= str_replace('\\/', '/', json_encode($set));
答案 0 :(得分:4)
我认为问题是你正在使用fetchColumn()获取总记录数,当你可能需要rowCount()时:
$total_records = $result->rowCount();
fetchColumn()调用只是从结果集中的下一条记录中获取下一列。因此,如果您的查询返回2行,如下所示:
fruit | color
--------------
apple | red
grapes | green
...然后在执行后调用结果上的fetchColumn()会给你“苹果”。同时,rowCount()会给你2号(两行)。
编辑:在关于设置查询以使用参数的第一条评论中,还要注意Rasclatt的建议。这是非常好的建议。
答案 1 :(得分:4)
我觉得有必要加上这个(这不是答案)
在你的&#34; PDO&#34;代码我看到2个地方容易受到SQL注入攻击。现在你可能正在升级,所以它可以与PHP 7一起工作,但忽略这一点,是悲剧性的。
特别是
if(isset($_GET['cat_id'])){
$result=$con->prepare("SELECT * FROM tbl_news_category c,tbl_news n WHERE c.cid=n.cat_id and c.cid='".$_GET['cat_id']."' ORDER BY n.id DESC");
}else if(isset($_GET['latest_news'])){
$limit=$_GET['latest_news'];
$result=$con->prepare("SELECT * FROM tbl_news_category c,tbl_news n WHERE c.cid=n.cat_id ORDER BY n.id DESC LIMIT $limit");
}
$_GET
和扩展名$limit
都是您直接连接到SQL的用户输入。无论何时将任何内容连接到SQL命令中,都需要对其进行绑定或彻底清理(例如,针对白名单进行检查,例如在变量列名称的情况下,例如在选择排序时)。这需要完成&#34;在查询的清晰视图中#34;换句话说,如果你无法在同一个地方看到如何清理输入,则需要绑定它。这就是我所说的失败点。
修复它们就是这样做的。
$params = [];
if(isset($_GET['cat_id'])){
$result=$con->prepare("SELECT * FROM tbl_news_category c,tbl_news n WHERE c.cid=n.cat_id and c.cid=:cat_id' ORDER BY n.id DESC");
$params = [':cat_id' => $_GET['cat_id']];
}else if(isset($_GET['latest_news'])){
$result=$con->prepare("SELECT * FROM tbl_news_category c,tbl_news n WHERE c.cid=n.cat_id ORDER BY n.id DESC LIMIT :limit");
// to bind to limit clause you have to use BindValue
$result->bindValue(':limit', (int)$_GET['latest_news'], PDO::PARAM_INT);
}
... other code ...
$result->execute($params);
您可以在第一种情况下使用$result->bindValue(':cat_id', $_GET['cat_id'])
,但我想展示绑定的数组方法以及bind
调用方法。如果你这样做,你可以一起跳过$param
。但是如果要绑定很多变量,数组方法很有用,所以我想我也会这样做。
并非所有内容都可以绑定,例如列名称。一个例子是允许用户选择要排序的列。这种接缝就像一个小东西,但即使在那里你也不能只在查询中连接用户输入。在这种情况下,正如我之前所说的那样,我会根据列名列表对它们进行检查,允许它们在查询的清晰视图中进行排序,因此无法绕过检查。
对于这些情况,您可以执行以下操作(例如$ _GET [&#39; orderby&#39;] =&#39; first&#39;):
$whitelist = ['first','last','age'];
$orderby = false;
if(!empty($_GET['orderby']) && false !== ( $index = array_search($_GET['orderby'], $whitelist))){
$orderby = $whitelist[$index];
}
$sql = 'SELECT * FROM table WHERE 1';
if($orderby) $sql =. ' ORDER BY '.$orderby;
通过这种方式,我们可以检查用户输入而不是实际使用它,$orderby
的值是$whitelist[$index]
的值,因此即使在这里也没有向查询添加用户输入。如果存在一些代码错误,那么我们就不用担心会偷偷摸摸。
即使您认为它的固定数据需要清理或绑定。代码可以改变,并且在前端执行此操作需要更少的工作,然后处理如果您的站点遭受重大攻击的后果。您对固定数据的看法可能是$_SESSION
中存储的内容,但由于它存储在全局位置,因此某些代码更新可能会更改该值的来源且不清楚在那里进行了更改,它使查询隐藏在代码中的某个地方。这就是为什么甚至需要在查询时清除数据的原因。
起初可能有点令人困惑,但它确实非常简单易行。希望有所帮助。
现在修复它!