将旧mysql更改为pdo时无法工作

mec1mxoz  于 2021-06-21  发布在  Mysql
关注(0)|答案(2)|浏览(362)

我已经将旧的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));
hfyxw5xn

hfyxw5xn1#

我想补充一下(这不是答案)
在您的“pdo”代码中,我看到有两个地方易受sql注入攻击。现在您可能正在升级,以便它可以与PHP7一起使用,但忽略这一点是悲剧。
明确地

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命令中时,都需要对其进行绑定或彻底清理(例如,在选择排序时检查白名单,例如在变量列名的情况下)。这需要在“查询的清晰视图”中完成,换句话说,如果你不能在同一个地方看到输入是如何被清理的,那么就需要绑定它。这就是我所说的失败点。
为了解决这些问题,就这样做。

$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 一起。但是如果有很多变量需要绑定,那么array方法是很有用的,所以我想我也会展示一下。
并非所有内容都可以绑定,例如列名。例如,允许用户选择要排序的列。这就像一件小事,但即使这样,也不能在查询中串联用户输入。在本例中,正如我之前所说的,我将对照允许它们排序的列名列表进行检查,并且在查询的清晰视图中进行检查,因此无法绕过检查。
对于这些情况,您可以这样做(例如$\u get['orderby']='first'):

$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 但由于它存储在全局位置,某些代码更新可能会更改该值来自何处,而且不清楚在何处进行了更改,这使得隐藏在代码中某个位置的查询变得值得尊敬。这就是为什么即使是caned数据也需要在查询时进行清理。
一开始可能会有点混乱,但其实很简单,很容易做到。希望有帮助。
现在修好它!

f3temu5u

f3temu5u2#

我认为问题是您使用fetchcolumn()来获取总记录数,而您可能需要rowcount():

$total_records = $result->rowCount();

fetchcolumn()调用只是从结果集中的下一条记录中获取下一列。因此,如果您的查询返回如下两行:

fruit  | color
--------------
apple  | red
grapes | green

…然后在执行结果后对其调用fetchcolumn(),将得到“apple”。同时,rowcount()将给出数字2(两行)。
编辑:还要注意rasclatt在第一条评论中关于设置查询以使用参数的建议。这是个很好的建议。

相关问题