53

現在、MySQLi をいじって、すべてがどのように機能するかを理解しようとしています。私の現在のプロジェクトでは、すべてが正しいことを確認し、コードをすばやくデバッグするために、コーディング中に常にクエリ文字列をエコーアウトするのが好きです。しかし...準備されたMySQLiステートメントでこれを行うにはどうすればよいですか?

例:

$id = 1;
$baz = 'something';

if ($stmt = $mysqli->prepare("SELECT foo FROM bar WHERE id=? AND baz=?")) {
  $stmt->bind_param('is',$id,$baz);
  // how to preview this prepared query before acutally executing it?
  // $stmt->execute();
}

私はこのリストを調べてきました(http://www.php.net/mysqli ) しかし、運はありません。


編集

まあ、MySQLi 内からそれが不可能な場合は、おそらく次のようなものに固執します。

function preparedQuery($sql,$params) {
  for ($i=0; $i<count($params); $i++) {
    $sql = preg_replace('/\?/',$params[$i],$sql,1);
  }
  return $sql;
}

$id = 1;
$baz = 'something';

$sql = "SELECT foo FROM bar WHERE id=? AND baz=?";

echo preparedQuery($sql,array($id,$baz));

// outputs: SELECT foo FROM bar WHERE id=1 AND baz=something

明らかに完璧にはほど遠いです。これはまだかなり冗長であるためです (これは私が防止したかったことです)。また、MySQLi によってデータがどのように処理されているかについてのアイデアも得られません。しかし、この方法で、すべてのデータが存在し、適切な場所にあるかどうかをすばやく確認できると思います。変数を手動でクエリに組み込むよりも、時間を節約できます。

4

6 に答える 6

12

私はあなたができるとは思いません-少なくともあなたが望んでいた方法では。クエリ文字列を自分で作成して実行するか(つまり、ステートメントを使用せずに)、その機能をサポートするラッパーを探すか作成する必要があります。私が使用しているのはZend_Dbで、これが私が行う方法です。

$id = 5;
$baz = 'shazam';
$select = $db->select()->from('bar','foo')
                       ->where('id = ?', $id)
                       ->where('baz = ?', $baz); // Zend_Db_Select will properly quote stuff for you
print_r($select->__toString()); // prints SELECT `bar`.`foo` FROM `bar` WHERE (id = 5) AND (baz = 'shazam')
于 2009-06-07T23:26:48.920 に答える
9

私は過去にこれに苦労しました。それで、それを回避するために、SQL、フラグ、および変数に基づいてSQLを構築するための小さな関数を作成しました。

//////////// Test Data //////////////
$_GET['filmID'] = 232;
$_GET['filmName'] = "Titanic";
$_GET['filmPrice'] = 10.99;

//////////// Helper Function //////////////
function debug_bind_param(){
    $numargs = func_num_args();
    $numVars = $numargs - 2;
    $arg2 = func_get_arg(1);
    $flagsAr = str_split($arg2);
    $showAr = array();
    for($i=0;$i<$numargs;$i++){
        switch($flagsAr[$i]){
        case 's' :  $showAr[] = "'".func_get_arg($i+2)."'";
        break;
        case 'i' :  $showAr[] = func_get_arg($i+2);
        break;  
        case 'd' :  $showAr[] = func_get_arg($i+2);
        break;  
        case 'b' :  $showAr[] = "'".func_get_arg($i+2)."'";
        break;  
        }
    }
    $query = func_get_arg(0);
    $querysAr = str_split($query);
    $lengthQuery = count($querysAr);
    $j = 0;
    $display = "";
    for($i=0;$i<$lengthQuery;$i++){
        if($querysAr[$i] === '?'){
            $display .= $showAr[$j];
            $j++;   
        }else{
            $display .= $querysAr[$i];
        }
    }
    if($j != $numVars){
        $display = "Mismatch on Variables to Placeholders (?)"; 
    }
    return $display;
}

//////////// Test and echo return //////////////

echo debug_bind_param("SELECT filmName FROM movies WHERE filmID = ? AND filmName = ? AND price = ?", "isd", $_GET['filmID'], $_GET['filmName'], $_GET['filmPrice']);

また、役立つ小さなオンラインツールを作成しました。

Mysqliプリペアドステートメントチェッカー

于 2012-07-25T20:19:51.100 に答える
6

最近、このプロジェクトを更新して、composer の統合、単体テストを含め、参照による引数の受け入れをより適切に処理できるようにしました (これには、php 5.6 への更新が必要です)。


を使用してこの同じ問題に対処するために作成したプロジェクトで受け取ったリクエストに応えて、あなたの問題に対処しているように見えるPDO拡張機能をmysqligithubに作成しました。

https://github.com/noahheck/E_mysqli

これは、ネイティブmysqliおよびmysqli_stmtクラスを拡張するクラスのセットであり、バインドされたパラメーターを準備されたクエリに補間し、結果のクエリ文字列に新しいプロパティとしてアクセスできるようにすることで、db サーバーで実行されるクエリの例を表示できるようにします。stmtオブジェクトで:

$mysqli  = new E_mysqli($dbHost, $dbUser, $dbPass, $dbName);

$query = "UPDATE registration SET name = ?, email = ? WHERE entryId = ?";

$stmt = $mysqli->prepare($query);

$stmt->bindParam("ssi", $_POST['name'], $_POST['email'], $_POST['entryId']);

$stmt->execute();

echo $stmt->fullQuery;

結果は次のとおりです。

UPDATE registration SET name = 'Sue O\'reilly', email = 'sue.o@example.com' WHERE entryId = 5569

fullQuery の値は、db サーバーの文字セットを考慮して適切にエスケープされることに注意してください。これにより、この機能はログ ファイルやバックアップなどに適したものになります。

これを使用するには、github プロジェクトの ReadMe で概説されているいくつかの注意事項がありますが、特に開発、学習、およびテストの場合、これはいくつかの役立つ機能を提供するはずです。

github プロジェクトで概説したように、拡張機能を使用した実際の経験はありません。mysqliこのプロジェクトは、姉妹プロジェクトのユーザーの要求で作成されたため、本番環境でこれを使用している開発者から提供できるフィードバックはありません。よろしくお願いします。

免責事項- 私が言ったように、私はこの拡張機能を作りました。

于 2014-07-26T17:46:03.363 に答える
3

死ぬように設定して、最後に実行されたクエリを出力するだけです。エラー処理は、クエリを修正するために使用できる意味のある情報を提供する必要があります。

于 2009-06-08T01:00:25.533 に答える