1

これまでに作成したコードは、プリペアドステートメントの名前付きプレースホルダーが1つしかない場合は正常に機能しますが、クエリに複数の条件がある場合は、データベースから結果が返されません。

例えば:

$query = array();
$query['columns'] = array('*');
$query['tables'] = array('esl_comments');
$query['where'] = array(
    'esl_comments.commentVisible' => array('=', 'Y')
);

正常に動作します。しかし、私が試してみると:

$query = array();
$query['columns'] = array('*');
$query['tables'] = array('esl_comments');
$query['where'] = array(
    'esl_comments.commentVisible' => array('=', 'Y'),
    'esl_comments.commentID' => array('=', '1'),
);

(追加のcommentIDパラメーターに注意してください)mySQLデータベースに条件を満たすデータがあるにもかかわらず、何も返されません。

私が書いたPDOコードは次のとおりです。

$sql ='SELECT ';
                foreach($query['columns'] as $column){ //What columnns do we want to fetch?
                    $sql.=$column . ", ";
                }
                $sql = rtrim($sql, " ,");
                $sql .=' FROM '; //Which tables will we be accessing?
                foreach($query['tables'] as $tables){
                    $sql.=$tables . ", ";
                }
                $sql = rtrim($sql, " ,"); //Get rid of the last comma
                $sql .=' WHERE ';

                if(array_key_exists('where', $query)) //check if a where clause was provided
                {
                    $fieldnames = array_keys($query['where']);
                    $count = 0;
                    $size = sizeof($fieldnames);
                    $bindings = array();
                    foreach($query['where'] as $where){

                        $cleanPlaceholder = str_replace("_", "", $fieldnames[$count]);
                        $cleanPlaceholder = str_replace(".", "", $cleanPlaceholder);
                        $sql.=$fieldnames[$count].$where[0].":".$cleanPlaceholder." AND ";
                        $bindings[$cleanPlaceholder]=$where[1];
                        $count++;
                    }
                    $sql = substr($sql, 0, -5);  //Remove the last AND
                }
                else{ //no where clause so set it to an always true check
                    $sql.='1=1';
                    $bindings=array('1'=>'1'); //Provide default bindings for the statement
                }

                $sql .= ';'; //Add the semi-colon to note the end of the query
                echo $sql . "<br/><br/>";
            //  exit();
                $stmt = $this->_connection->prepare($sql);

                foreach($bindings as $placeholder=>$bound){
                    echo $placeholder . " - " . $bound."<br/>";
                    $stmt->bindParam($placeholder, $bound);
                }

                $result = $stmt->execute();
                echo $stmt->rowCount() . " records<br/>";

                $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

クエリを動的に作成しているため、プレースホルダーからピリオドとアンダースコアを削除して、プレースホルダーをクリーンアップしています。したがって、「cleanPlaceholder」変数を使用しています。

生成されるクエリは次のようになります。

SELECT * FROM esl_comments WHERE esl_comments.commentVisible=:eslcommentscommentVisible AND esl_comments.commentID=:eslcommentscommentID;

そして、バインドされているパラメータは次のようになります。

eslcommentscommentVisible - Y
eslcommentscommentID - 1
4

1 に答える 1

4

bindParam参照が必要です

この問題は、foreachループでパラメーターをバインドする方法が原因で発生します。

foreach($bindings as $placeholder=>$bound){
    echo $placeholder . " - " . $bound."<br/>";
    $stmt->bindParam($placeholder, $bound);
}

bindParam参照が必要です。値ではなく変数をステートメントにバインドします。foreachループの変数は各反復の開始時にリセットされるため、への最後の参照のみ$boundがそのまま残り、すべてのプレースホルダーをそれにバインドすることになります。

そのため、コードに$query['where']エントリが1つしかない場合は機能しますが、複数のエントリが含まれている場合は失敗します。

この問題は2つの方法で解決できます。

参照による通過

foreach($bindings as $placeholder => &$bound) {  //pass $bound as a reference (&)
    $stmt->bindParam($placeholder, $bound);     // bind the variable to the statement
}

値渡し

bindValueの代わりに使用bindParam

foreach($bindings as $placeholder => $bound) {  
    $stmt->bindValue($placeholder, $bound);     // bind the value to the statement
}
于 2012-12-02T10:45:50.550 に答える