问题描述:
都知道自PHP 5.1.0 起,PDO就算是PHP的标配的一部分了,PDO提供了3个类PDO
,PDOStatement
和PDOException
,PDOException
这个类就不用说了,功能和定位啥的看名字都很清楚。
那么问题来了:为什么会同时存在PDO
和PDOStatement
这两个类?
为什么会有这样的疑问,先看下图(图片截取自@PHP官网手册):
图片是PDO
和PDOStatement
类所声明的方法,可以看出,这两个类提供的方法虽然绝大部分不同,但是明显核心方法有重叠或重复,比如:
PDO::query()
,PDO::exec()
都是执行一条SQL语句,只是返回不同
PDOStatement::execute()
也是执行一条SQL语句,只是语句被预处理过
PDOStatement::execute()
还好说,而PDO::query()
和 PDO::exec()
同时存在的必要性又是什么呢?而且还会造成使用和理解上面的不畅。
好吧,就算有同时存在的必要性
那么还是有一点为什么要同时存在这两个类呢?而不是一个类(假如只有 PDO
类)就将这两个类所能做的事情一起做了呢?PDO
类和 PDOStatement
类之间是什么关系呢?
如果 PDO
类用来执行SQL和管理链接,而 PDOStatement
类只用来处理结果集,那么感觉就舒服顺畅多了。
希望有大牛能给予解释 PHP
的 PDO
这么设计的考虑是什么,真诚感谢~
仅有的幸福2017-05-16 13:13:25
私の個人的な理解を述べますので、間違いがあればご指摘ください。
PDO クラスを初めて見てみる
query() と prepare() の両方が PDOStatement オブジェクトを返すことがわかります。これは、PDOStatement が結果セットを操作できることを意味します。
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 の結果セットではなく、影響を受ける行の数のみが返されます。これを直接走査することはできません。クエリを使用または実行するには、公式の推奨事項に従ってください。
私が理解しているのは大体こんな感じです。
PHP中文网2017-05-16 13:13:25
リーリー
上記の 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:
を使用する必要があります。
リーリー