PHPで、パラメーター化されたクエリを使用してPDOでMySQLデータベースにアクセスする場合、(すべてのトークンを置き換えた後)最終クエリを確認するにはどうすればよいですか?
データベースによって実際に実行されるものを確認する方法はありますか?
だから、レコードの完全なソリューションを得るために、最終的に自分の質問に答えると思います。しかし、この手がかりを提供してくれた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]
本番環境ではこれを実行しないでください!!!
パラメータ化された値を持つ準備済みステートメントを使用することは、SQLの文字列を動的に作成するための単なる別の方法ではありません。データベースで準備済みステートメントを作成し、パラメーター値のみを送信します。
したがって、おそらくデータベースに送信されるのは、PREPARE ...
、次にSET ...
、最後にEXECUTE ...
になります。
そのようなクエリは実際にデータベースに送信されなかったため、同等の結果が得られたとしても、SELECT * FROM ...
のようなSQL文字列を取得することはできません。
PDOStatement->debugDumpParams
を使用できる場合があります。 PHPドキュメント を参照してください。
クエリログをチェックして、準備されたステートメントとして実行された正確なクエリを確認します。
最初は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';
さもないと、ログが膨大になります。
実際のクエリを印刷するためにやったことは少し複雑ですが、動作します:)
変数をステートメントに割り当てるメソッドには、次のような変数がもう1つあります。
$this->fullStmt = str_replace($column, '\'' . str_replace('\'', '\\\'', $param) . '\'', $this->fullStmt);
どこ:$column
は私のトークンです$param
は、トークンに割り当てられている実際の値です$this->fullStmt
は、トークンが置換された印刷専用ステートメントです
実際のPDO割り当てが行われたときに、トークンを値に置き換えるだけです。
私はあなたを混乱させず、少なくとも正しい方向にあなたを向けたと思います。
私はあなたができるとは思わないが、誰かが私を間違っていると証明してくれることを願っている。
クエリを印刷でき、そのtoStringメソッドは、置換なしでsqlを表示することを知っています。複雑なクエリ文字列を作成している場合には便利ですが、値を含む完全なクエリを提供することはできません。