web-dev-qa-db-ja.com

準備されたステートメントの内容を表示するにはどうすればよいですか?

PHPでmysqliを使用してプリペアドステートメントを使用する方法を学習しています。通常、クエリで問題が発生した場合は、画面にエコーして、次のように表示されます。最初のステップ。

プリペアドステートメントでそれを行うにはどうすればよいですか?

変数が代入された後のSQLステートメントを見たいのですが。

21
Stomped

プリペアドステートメントの使用:

  • ステートメントを準備すると、MySQLサーバーに送信されます
  • 変数をバインドしてステートメントを実行すると、変数のみがMySQLサーバーに送信されます
  • そして、ステートメント+バインドされた変数は、MySQLサーバーで実行されます-ステートメントが実行されるたびに「準備」を再実行することなく(これが、同じステートメントが実行されるときに準備されたステートメントがパフォーマンスに役立つ可能性がある理由です数回)

PHP側にはSQLクエリの「構築」がないため、実際にそのクエリを取得する方法はありません。

つまり、SQLクエリを表示する場合は、プリペアドステートメントではなくSQLクエリを使用する必要があります。

20
Pascal MARTIN
Mysql_stmt_prepare()およびmysql_stmt_execute()C API関数で実行される準備済みステートメントの場合、サーバーは準備行と実行行を一般クエリログに書き込み、ステートメントがいつ準備され実行されるかを確認できるようにします。
[...]サーバーは次の行を一般的なクエリログに書き込みます。
準備[1] SELECT?
[1] SELECT3を実行します

したがって、デバッグの目的で、 一般ログ をアクティブにし、そのファイルを監視します。

編集:ああ、質問には[mysqli]タグがあります...それを完全に見落としていました。
ステートメントがまったく実行されない場合、途中でエラーが発生していないことを(ダブル/トリプル)チェックしましたか?

echo "<pre>Debug: start</pre>\n";

$mysqli = new mysqli('localhost', 'localonly', 'localonly', 'test');
if ($mysqli->connect_error) {
  die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}

$result = $mysqli->query('CREATE TEMPORARY TABLE foo (id int auto_increment, x int, primary key(id))');
if ( false=== $result) { 
 die('error : '. $mysqli->error);
}

$stmt = $mysqli->prepare('INSERT INTO foo (x) VALUES (?)');
if ( false===$stmt ) {
  die ('prepare() failed: ' . $mysqli->error);
}

$result = $stmt->bind_param('i', $x);
if ( false===$result ) {
  die('bind_param() failed');
}

$x = 1;
$result = $stmt->execute();
if ( false===$result ) {
  die('execute() failed: '.$stmt->error);
}

echo "<pre>Debug: end</pre>\n";
13
VolkerK

私は通常、パラメータを使用して準備されたSQLをデバッグする必要があるときにこれを行います。

準備と実行の例:

$sql = "SELECT VAL1, VAL2 FROM TABLE(?, '?', '?', '?', '?', ?, '?', '?', '?')";
$prep = ibase_prepare( $sql ) or die("Error");
$query = ibase_execute($prep, $param1, $param2, .....) or $err = true;
                              ^^^^^^^^^^^^^^^^^^^^^^^

文の結果のSQLをデバッグする簡単な方法は次のとおりです。

printf( str_replace('?', '%s', $sql), $param1, $param2, ....);
                                      ^^^^^^^^^^^^^^^^^^^^^^

準備したSQL文字列の?を1つの%sに置き換えて、1つのprintfを実行するだけで済みます。 printfは、すべてを1つの文字列として解釈し、各パラメーターを、置き換えられた各%sに配置するものと見なします。

3
NetVicious

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


デフォルトのmysqliクラスと_mysqli_stmt_クラスを拡張するクラスのセットを作成して、潜在的なクエリ文字列のレンディションを表示できるようにしました。これにより、探しているものが提供されます。

https://github.com/noahheck/E_mysqli

これは、クエリ文字列をprepare()するとカスタムの_mysqli_stmt_オブジェクトを返す通常のmysqliオブジェクトの(近い)ドロップイン置換です。パラメータをバインドした後、_E_mysqli_を使用すると、結果のクエリ文字列をstmtオブジェクトの新しいプロパティとして表示できます。

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

$query = "INSERT INTO registration SET name = ?, email = ?";

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

$stmt->bind_param("ss", $_POST['name'], $_POST['email']);

$stmt->execute();

echo $stmt->fullQuery;
_

結果は次のようになります。

_INSERT INTO registration SET name = 'John Doe', email = '[email protected]'
_

この拡張機能の使用にはいくつかの注意点があります(githubプロジェクトのREADME)で説明されています)が、アプリケーションの厄介な領域のトラブルシューティングや、手続き型からオブジェクト指向スタイルへの移行のために、これはほとんどのユーザーにとってのヘルプのレベル。

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

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

1
myesain

Pascal MARTIN(+1)に同意するので、デバッグのための別の手法を提案します:var_dump()またはステートメントに挿入するすべての変数をログに記録します。そうすれば、データが間違っているかどうかを判断できます。論理的に間違ったSQL。

0
chelmertz

Lottip のようなツールを使用できます。アイデアはMySQLプロキシのように機能します。 MySQLパケットを解析し、クエリとそのパラメータを抽出するため、プリペアドステートメントとその内容を確認できます。

0
Orderbynull