web-dev-qa-db-ja.com

MySQLiプリペアドステートメントをエコーする方法は?

現時点では、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によってデータで何が行われているのかもわかりません。しかし、このようにすれば、すべてのデータが適切な場所にあるかどうかをすぐに確認でき、フィッティングと比較してsome時間を節約できます変数をクエリに手動で追加します。これは、多くの変数で苦痛になる場合があります。

45
Alec

少なくともあなたが望んでいた方法ではない-私はあなたができるとは思わない。クエリ文字列を自分で作成して実行する(つまり、ステートメントを使用しない)か、その機能をサポートするラッパーを探すか作成する必要があります。私が使用するのは 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')
10
karim79

過去にこれに苦労しました。そのため、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 Prepare Statement Checker

6
mustbebuilt

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

4
Langerz

最近、このプロジェクトを更新してcomposer統合、単体テスト、および引数の参照による処理を改善しました(これにはphp 5.6への更新が必要です)。


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

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 = '[email protected]' WHERE entryId = 5569

FullQueryの値は、dbサーバーの文字セットを考慮して適切にエスケープされることに注意してください。ログファイル、バックアップなど.

GithubプロジェクトのReadMeで説明されているように、これを使用するにはいくつかの注意事項がありますが、特に開発、学習、テストに関しては、これはいくつかの有用な機能を提供するはずです。

Githubプロジェクトで概説したように、mysqli拡張機能を使用した実用的な経験はなく、このプロジェクトは姉妹プロジェクトのユーザーのリクエストで作成されたため、フィードバックを提供できます。本番環境でこれを使用している開発者からは大歓迎です。

免責事項-私が言ったように、私はこの拡張を行いました。

2
myesain

Mysqlサーバーでログクエリをオンにできます。コマンドを実行するだけです:

sql> SHOW VARIABLES LIKE "general_log%";
sql> SET GLOBAL general_log = 'ON';

ログファイルでクエリを監視します。テスト後、ログオフします。

sql> SET GLOBAL general_log = 'OFF';
0
alchemist