web-dev-qa-db-ja.com

PDOを使用したPHPで、最終的なSQLパラメーター化されたクエリを確認する方法

PHPで、パラメーター化されたクエリを使用してPDOでMySQLデータベースにアクセスする場合、(すべてのトークンを置き換えた後)最終クエリを確認するにはどうすればよいですか?

データベースによって実際に実行されるものを確認する方法はありますか?

135
JB Hurteaux

だから、レコードの完全なソリューションを得るために、最終的に自分の質問に答えると思います。しかし、この手がかりを提供してくれたBen JamesとKailash Baduに感謝しなければなりません。

短い答え
ベン・ジェームスが述べたとおり:NO
トークン付きクエリとパラメータは別々にデータベースに送信されるため、完全なSQLクエリはPHP側には存在しません。データベース側にのみ、完全なクエリが存在します。

PHP側でトークンを置換する関数を作成しようとしても、置換プロセスがSQLのものと同じであることを保証しません(トークン型、bindValue vs bindParamなどの巧妙なもの...)

回避策
ここで、カイラシュ・バドゥの答えを詳しく説明します。すべてのSQLクエリを記録することで、サーバーで実際に実行されているものを確認できます。 mySQLでは、my.cnf(または、Wampサーバーの場合はmy.ini)を更新し、次のような行を追加することでこれを実行できます。

log=[REPLACE_BY_PATH]/[REPLACE_BY_FILE_NAME]

本番環境ではこれを実行しないでください!!!

53
JB Hurteaux

パラメータ化された値を持つ準備済みステートメントを使用することは、SQLの文字列を動的に作成するための単なる別の方法ではありません。データベースで準備済みステートメントを作成し、パラメーター値のみを送信します。

したがって、おそらくデータベースに送信されるのは、PREPARE ...、次にSET ...、最後にEXECUTE ...になります。

そのようなクエリは実際にデータベースに送信されなかったため、同等の結果が得られたとしても、SELECT * FROM ...のようなSQL文字列を取得することはできません。

27
Ben James

PDOStatement->debugDumpParamsを使用できる場合があります。 PHPドキュメント を参照してください。

26
Michael

クエリログをチェックして、準備されたステートメントとして実行された正確なクエリを確認します。

9
Kailash Badu

最初はPDOを監視するためにログを有効にすることを避けましたが、それは面倒だと思ったからです。 MySQLを再起動する必要はありません(5.1.9以降):

このSQLをphpMyAdminまたは高いdb特権を持つ可能性のある他の環境で実行します。

SET GLOBAL general_log = 'ON';

ターミナルで、ログファイルを末尾にします。私がここにいました:

>Sudo tail -f /usr/local/mysql/data/myMacComputerName.log

次の端末コマンドでmysqlファイルを検索できます。

>ps auxww|grep [m]ysqld

PDOはすべてをエスケープするので、書くことはできません。

$dynamicField = 'userName';
$sql = "SELECT * FROM `example` WHERE `:field` = :value";
$this->statement = $this->db->prepare($sql);
$this->statement->bindValue(':field', $dynamicField);
$this->statement->bindValue(':value', 'mick');
$this->statement->execute();

作成する理由:

SELECT * FROM `example` WHERE `'userName'` = 'mick' ;

エラーは発生せず、空の結果になりました。代わりに使用する必要がありました

$sql = "SELECT * FROM `example` WHERE `$dynamicField` = :value";

取得するため

SELECT * FROM `example` WHERE `userName` = 'mick' ;

完了したら、次を実行します。

SET GLOBAL general_log = 'OFF';

さもないと、ログが膨大になります。

5
Chris Adams

それを行う最も簡単な方法は、mysql実行ログファイルを読み取ることであり、実行時に実行できます。

ここに素敵な説明があります:

MySQLで最後に実行されたクエリの表示方法

1
Cristiano

実際のクエリを印刷するためにやったことは少し複雑ですが、動作します:)

変数をステートメントに割り当てるメソッドには、次のような変数がもう1つあります。

$this->fullStmt = str_replace($column, '\'' . str_replace('\'', '\\\'', $param) . '\'', $this->fullStmt);

どこ:
$columnは私のトークンです
$paramは、トークンに割り当てられている実際の値です
$this->fullStmtは、トークンが置換された印刷専用ステートメントです

実際のPDO割り当てが行われたときに、トークンを値に置き換えるだけです。

私はあなたを混乱させず、少なくとも正しい方向にあなたを向けたと思います。

1
6bytes

私はあなたができるとは思わないが、誰かが私を間違っていると証明してくれることを願っている。

クエリを印刷でき、そのtoStringメソッドは、置換なしでsqlを表示することを知っています。複雑なクエリ文字列を作成している場合には便利ですが、値を含む完全なクエリを提供することはできません。

0
Scott Saunders