构建动态PDO语句的更好方法

时间:2013-02-19 22:50:55

标签: php mysql pdo

我正在尝试构建动态PDO SQL语句。有关如何做得更好的任何想法?

我跑这个时不断得到array(3) { [0]=> string(5) "00000" [1]=> NULL [2]=> NULL } free ......

所以我的MySQL PDO语句看起来效果不好!

有关如何解决这个问题的想法吗?

$park = $_POST["park"];
$lecturestyle_id = $_POST["lecturestyle"];
$group_size = $_POST["groupsize"];
$roomstructure_id = $_POST["roomstructure"];
$array = explode(",", $_POST["facilities"]);

// change Mon here

echo '<td class="gridSide">
Mon
';

// build facilities search

for($i = 0; $i < count($array); $i++){  
    if ($array[$i]!=0) {
    $fac .= 'AND facilities_id='.$array[$i].' ';
    }
    else
    $fac .= '';
}

echo '</td>';


for ($i = 1; $i <= 9; $i++) 
{

        // change mon here

        echo '<td class="box" id="mon'.$i.'">';

        // dynamically build sql query

        $sql = 
        "
        SELECT * FROM ts_room rm
        LEFT JOIN ts_roomfacilities rf
        ON rm.id = rf.room_id
        LEFT join ts_facilities f
        ON f.id = rf.facilities_id
        LEFT JOIN ts_building b
        ON rm.building_id=b.id
        WHERE capacity>=".$group_size.' ';

        $sql .= $fac;

        if($park!="Any") {
        $sql .= " AND b.park_id=".$park;
        }

        if($lecturestyle_id!="Any") {
        $sql .= " AND lecturestyle_id=".$lecturestyle_id;
        }

        if($roomstructure_id!="Any") {
        $sql .= " AND roomstructure_id=".$roomstructure_id;
        }

        $sql .= " AND rm.id NOT IN
        (SELECT COUNT(*)
         FROM ts_request rq
         LEFT JOIN ts_allocation a ON a.request_id = rq.id
         WHERE 
         day_id=1 AND period_id=".$i."
         OR a.status IS NOT NULL
         AND a.status IN ('Pending','Declined','Failed'))";

         $stm = $pdo->prepare( $sql );
         $rows = $stm->fetchColumn();

         echo $rows.'<br>free</td>';            
         echo '</td>';

}

1 个答案:

答案 0 :(得分:0)

一个有趣的事实。每个人只有提及 SQL注入和准备语句,而没有人想编写代码:)

虽然我能理解它:PDO在条件查询方面非常弱,所以任务将非常辛苦。
与任何其他API一样,PDO仅适用于初学者手册中的基本任务,并且对于任何现实生活中的问题都没有为开发人员提供真正的帮助。

所以,我会给你一个safeMysql示例,它既安全方便
与PDO兼容,但您可以使用它来获得所有好处。

所以,想法是解析占位符而不是整个查询,而只是在任意查询部分。比如,您的设施部分:

$fac_sql = '';
foreach($array as $facility){   
    if ($facility) {
       $fac_sql .= $db->parse(' AND facilities_id=?i',$facility);
    }
}

现在,您在$fac_sql变量中具有语法正确的语句 其他部分也是如此

$cond = '';
if($park!="Any") {
    $cond .= $db->parse(' AND b.park_id=?s',$park);
}
if($lecturestyle_id!="Any") {
    $cond .= $db->parse(" AND lecturestyle_id=?s",$lecturestyle_id);
}
if($roomstructure_id!="Any") {
    $cond .= $db->parse(" AND roomstructure_id=?s",$roomstructure_id);
}

...以及整个查询:

$sql = "
SELECT * FROM ts_room rm
LEFT JOIN ts_roomfacilities rf
ON rm.id = rf.room_id
LEFT join ts_facilities f
ON f.id = rf.facilities_id
LEFT JOIN ts_building b
ON rm.building_id=b.id
WHERE capacity >= ?s;
?p
?p
AND rm.id NOT IN
(SELECT COUNT(*)
 FROM ts_request rq
 LEFT JOIN ts_allocation a ON a.request_id = rq.id
 WHERE 
 day_id=1 AND period_id=?i
 OR a.status IS NOT NULL
 AND a.status IN ('Pending','Declined','Failed'))";

$rows = $db->getCol($sql,$group_size,$fac_sql,$cond,$i);

(代码已经过测试,但仅作为示例!)。

另一个safeMysql的好处是,如果出现错误,它将返回Mysql错误消息和整个查询。您将能够修复错误或在控制台中尝试查询以进行测试。

所以 - 这就是条件查询的一般方法。

至于您查询的特定问题 - 它与PDO或预准备语句或条件查询构建无关。查询逻辑中存在缺陷 您必须以纯文本形式编写查询,并使用console / phpadmin / sqlyog / whatever进行尝试。您也可以在stackoverflow上请求此 SQL 的帮助 只要您的查询正常工作,您就可以开始动态构建它。

另外,我觉得它过于复杂,需要简化。可以拆分成几个更简单的查询。同样在循环中运行这样的怪物也是一个很大的缺陷。最好在一次通话中重写它。