問題の説明:
PHP 5.1.0 以降、PDO は PHP の標準部分として、PDO
、PDOStatement code>、および 3 つのクラスを提供していることは誰もが知っています。
PDOException
、PDOException
言うまでもなく、その機能と位置付けは名前から非常に明らかです。
次に疑問が生じます。なぜ 2 つのクラス PDO
と PDOStatement
が同時に存在するのでしょうか?
なぜこのような質問があるのでしょうか? まず、以下の図をご覧ください (写真は @PHP 公式 Web サイトのマニュアルから引用):
この図は、PDO
クラスと PDOStatement
クラスによって宣言されたメソッドを示しています。これら 2 つのクラスによって提供されるメソッドのほとんどは異なっていますが、コアは異なっていることがわかります。メソッドは明らかに Overlap またはrepeat です。次のようなものです。
PDO::query()
、PDO::exec()
は両方とも SQL ステートメントを実行しますが、戻り値は異なります。
PDOStatement::execute()
も SQL ステートメントを実行しますが、ステートメントは前処理されています
PDOStatement::execute()
は問題ありませんが、PDO::query()
と PDO::exec()
は次の場所に存在します。同時に何が必要なのか?また、使用や理解が困難になります。
そうですね、同時に存在する必要があるとしても
それでも重要な点はありますなぜこれら 2 つのクラスが同時に存在するのでしょうか? 1 つのクラス (PDO
クラスしかない場合) の代わりに、これら 2 つのクラスで実行できることを一緒に実行してみてはどうでしょうか。 PDO
クラスと PDOStatement
クラスの関係は何ですか?
PDO
クラスを SQL の実行と接続の管理に使用し、PDOStatement
クラスを結果セットの処理のみに使用すると、より快適でスムーズになります。 。
誰かが PHP
の PDO
の設計上の考慮事項を説明してくれることを願っています。よろしくお願いします~
私の理解では、1つは通常のSQLの実行に使用され、もう1つはパラメーターのバインドなどに使用できるということです...
私の個人的な理解を述べますので、間違いがあればご指摘ください。
リーリーPDO クラスを初めて見てみる
query() と prepare() の両方が PDOStatement オブジェクトを返すことがわかります。これは、PDOStatement が結果セットを操作できることを意味します。
プリペアド ステートメントのパラメーターを引用符で囲む必要はありません。アプリケーションがプリペアド ステートメントのみを使用する場合、開発者は SQL インジェクションが発生しないことを確認できますPDO::prepare をもう一度見てみると、マニュアルには準備済みステートメントを実行すると書かれていますが、実際には準備済みステートメント PDOStatement を取得し、PDOStatement::execute() を呼び出して実際に SQL を実行します。
通常、一部のプロジェクトでは SQL ステートメントを実行するために準備を使用します。このアプローチは、SQL インジェクションを防止し、同じテンプレート SQL のクエリのパフォーマンスを向上させるためのものです。公式マニュアルの内容が紹介されています。
クエリは解析 (または準備) するだけで済みます。クエリが準備されると、データベースはクエリを実行するための計画を分析、コンパイル、最適化するため、このプロセスにはかなりの時間がかかることがあります。異なるパラメーターを使用して同じクエリを何度も繰り返す必要がある場合、アプリケーションの速度が低下します。プリペアド ステートメントを使用すると、分析、コンパイル、最適化のサイクルが繰り返されることがなくなり、プリペアド ステートメントの実行速度が向上します。 .
(ただし、クエリはエスケープされていない入力で構築されていますが、SQL インジェクションは依然として可能です)。PDO::query と PDO::exec の違いについて投稿者が述べたことについては、次のようになります:query は select ステートメントのみを実行し、exec は実行します。 select、insert、update、delete を実行します
PDO::query SQL ステートメントを実行し、渡された場合は PDOStatement オブジェクトを返します
PDO::exec SQL ステートメントを実行し、影響を受ける行の数を返します。この関数は結果コレクションを返しません。
PDOStatement::execute は PDOStatement のサブ関数であり、SQL インジェクションのセキュリティ問題を考慮せずにパラメーターのバインドをサポートすることも特徴です。もう 1 つの特徴は、テンプレート SQL と同様に、複数の実行をサポートすることです。パフォーマンス。
1 つのステートメントのみをクエリする場合、クエリを使用する利点は、クエリによって返された結果セットを直接走査できることです。
exec を使用して実行すると、PDOStatement の結果セットではなく、影響を受ける行の数のみが返されます。これを直接走査することはできません。クエリを使用または実行するには、公式の推奨事項に従ってください。
私が理解しているのは大体こんな感じです。
リーリー
上記の 3 つのメソッドはすべて SQL を実行できます。わかりにくい場合は、3 番目のメソッドのみを使用できます。
exec と query がそれを実現できる限り、prepare+execute も実現できます。
そして prepare+execute は可能です。パラメータ化されたクエリの前処理など、exec と query は実装できません。たとえば、実行する SQL ステートメントに外部パラメータがない場合は、exec と query を使用することになります。簡潔に言うと、exec は影響を受ける行を直接返すことができるため、単一の書き込み操作 (INSERT/UPDATE/DELETE) ステートメントの実行には明らかに exec の方が適しています。クエリを使用する場合、影響を受ける行を取得するには rowCount() を呼び出す必要があります。 as :
$db->query($sql)->rowCount();
外部パラメータなしで SQL を実行して SELECT 結果を取得する場合は、exec の代わりに query を使用する必要があります。
$db->query($sql)->fetchAll();
$db->query($sql)->rowCount();
当如果你执行没有外来参数的SQL获取SELECT结果,这时则应该用query而不是exec:
$db->query($sql)->fetchAll();
入力パラメータを使用して SQL を実行する場合、SQL インジェクションを防ぐために、prepare:を使用する必要があります。 リーリー