0

動的 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>';

}
4

1 に答える 1

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 のもう 1 つの利点は、エラーが発生した場合に Mysql エラー メッセージとクエリ全体の両方が返されることです。エラーを修正するか、テストのためにコンソールでクエリを試すことができます。

つまり、これが一般的な条件付きクエリのあり方です。

クエリに関する特定の問題については、PDO、準備されたステートメント、または条件付きクエリの構築とは無関係です。クエリ ロジックのどこかに欠陥があります。
クエリをプレーン テキストで記述し、console/phpadmin/sqlyog/whatever で試す必要があります。このSQLについても、stackoverflowで支援を求めることができます。
クエリが機能するようになるとすぐに、動的に構築を開始できます。

また、かなり複雑すぎるので、単純化する必要があると感じています。いくつかの簡単なクエリに分割できます。また、そのようなモンスターをループで実行することも大きな欠点です。ONEコールで書き直したほうがいいです。

于 2013-02-20T07:04:20.510 に答える