PHP PDOの詳しい説明

*文
*文オリジナル
2017-12-26 17:07:3321751ブラウズ

この記事では主に PHP の PDO クラスについて詳しく紹介します。PDO クラスは、PHP でデータベースをより便利に使用するのに役立ちます。 PDO を使用している皆様のお役に立てれば幸いです。

はじめに

PDO クラスを見てみましょう。 PDO は PHP Data Objects の略語で、「PHP でデータベースにアクセスするための軽量で互換性のあるインターフェイス」と説明されています。その不快な名前にもかかわらず、PDO は PHP でデータベースにアクセスするための魅力的な方法です。
MySQLi との違い

MySQLi と PDO は非常に似ていますが、主な違いは 2 つあります:

1. MySQLi は MySQL のみにアクセスできますが、PDO は 12 の異なるデータベースにアクセスできます

2. PDO には通常の関数呼び出し (mysqli_ *functions) がありません。
開始手順

まず第一に、PHP に PDO プラグインがインストールされているかどうかを確認する必要があります。 $test=new PDO() の結果をテストに使用できます。プロンプトにパラメーターが一致しないというメッセージが表示された場合は、PDO プラグインがインストールされていることがわかります。オブジェクトが存在しないというメッセージが表示された場合は、まず pho.ini で php_pdo_yourssqlserverhere.extis がコメント化されているかどうかを確認する必要があります。このような文がない場合は PDO をインストールする必要があるので、ここでは詳しく説明しません。

接続

ここで、サーバーが動作していることを確認し、データベースへの接続を開始します:

$dsn = 'mysql:dbname=demo;host=localhost;port=3306';
$username = 'root';
$password = 'password_here';
try {
 $db = new PDO($dsn, $username, $password); // also allows an extra parameter of configuration
} catch(PDOException $e) {
 die(&#39;Could not connect to the database:<br/>&#39; . $e);
}

$dsn を除き、すべてのステートメントと変数は一目瞭然です。 DSN はデータ ソース名を指し、複数の入力タイプがあります。最も一般的なものは、先ほど使用したものです。PHP 公式 Web サイトでは、他の利用可能な DSN について説明しています。

DSN の他の追加パラメーターを省略し、(mysql:) のようにデータベース ドライバーの後にコロンを置くだけで済みます。この場合、PDO はローカル データベースへの接続を試みます。 MySQLi を使用する場合と同様に、クエリでデータベース名を指定する必要があります。

最後に注意する必要があるのは、初期化オブジェクトを try-catch ブロックでラップしていることです。 PDOException は、クエリが失敗した場合ではなく、PDO 接続が失敗した場合にスローされます。必要に応じて、次のコード $db=line を使用して例外モードを選択できます。

$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

または、PDO の初期化中にパラメータを直接渡すこともできます:

$db = new PDO($dsn, $username, $password, array (
 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));

現在は間違った方法を使用しています - 失敗したときに false を返すだけです。理由はありません 例外は発生しません扱った。

基本的なクエリ

PDO でクエリおよび実行メソッドを使用すると、データベース クエリが非常に簡単になります。クエリ結果の行数を取得する場合、exec は非常に使いやすいため、SELECT クエリ ステートメントに非常に役立ちます。

次に、以下の例で両方のメソッドを見てみましょう:

$statement = <<<SQL
 SELECT *
 FROM `foods`
 WHERE `healthy` = 0
SQL;
 
$foods = $db->query($statement);

クエリが正しいと仮定すると、$foods は PDO ステートメント オブジェクトになり、これを使用して結果を取得するか、結果の数を確認できますこのクエリでセットが見つかりました。
行数

欠点は、PDO には返される行数を計算するための統一された方法が提供されていないことです。 PDO ステートメントには rowCount というメソッドが含まれていますが、このメソッドはすべての SQL ドライバーで動作することが保証されていません (幸いなことに、Mysql データベースでは動作します)。

SQL ドライバーがこのメソッドをサポートしていない場合は、2 つのオプションもあります。セカンダリ クエリ (SELECT COUNT(*)) を使用するか、単純なカウント ($foods) を使用して行数を取得します。

MySQL の例では幸いなことに、次の簡単な方法を使用して正しい行数を出力できます。

echo $foods->rowCount();

結果セットを反復処理する

これらのおいしい食べ物を出力することは、まったく難しいことではありません:

foreach($foods->FetchAll() as $food) {
 echo $food[&#39;name&#39;] . &#39;<br />&#39;;
}

注意すべき唯一のことは、PDO は Fetch もサポートしていることです。メソッド、このメソッドのみ 最初の結果が返されます。これは、1 つの結果セットのみをクエリする場合に非常に便利です。
ユーザー入力のエスケープ (特殊文字)

ユーザーが安全なデータを入力することを保証するために使用される (mysqli_) real_escape_string について聞いたことがありますか。 PDO には、入力文字列内の引用符内の特殊文字をエスケープできる quote と呼ばれるメソッドが用意されています。

$input: this is&#39;s&#39; a &#39;&#39;&#39;pretty dange&#39;rous str&#39;ing

エスケープ後、最終的に次の結果が得られます:

$db->quote($input): &#39;this is\&#39;s\&#39; a \&#39;\&#39;\&#39;pretty dange\&#39;rous str\&#39;ing&#39;
exec()

前述のように、exec() メソッドを使用して UPDATE、DELETE、INSERT 操作を実装できます。最後に、影響を受ける行の数を返します:

$statement = <<<SQL
 DELETE FROM `foods`
 WHERE `healthy` = 1;
SQL;
 
echo $db->exec($statement); // outputs number of deleted rows

準備されたステートメント

exec メソッドとクエリは今でも広く使用されており、PHP でサポートされていますが、PHP 公式 Web サイトでは依然として全員が使用することを要求しています。代わりに準備されたステートメント。なぜ?主な理由は、そのほうが安全だからです。準備されたステートメントは実際のクエリにパラメーターを直接挿入しないため、潜在的な SQL インジェクションの多くが回避されます。

ただし、何らかの理由で、PDO は実際には前処理を使用せず、SQL サーバーに渡す前に前処理をシミュレートしてステートメントにパラメータ データを挿入します。これにより、一部のシステムが SQL インジェクションに対して脆弱になります。

如果你的SQL服务器不真正的支持预处理,我们可以很容易的通过如下方式在PDO初始化时传参来修复这个问题:
 

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

接下来开始我们的第一个预处理语句吧:
 

$statement = $db->prepare(&#39;SELECT * FROM foods WHERE `name`=? AND `healthy`=?&#39;);
$statement2 = $db->prepare(&#39;SELECT * FROM foods WHERE `name`=:name AND `healthy`=:healthy)&#39;;

正如你所见,有两种创建参数的方法,命名的与匿名的(不可以同时出现在一个语句中)。然后你可以使用bindValue来敲进你的输入:
 

$statement->bindValue(1, &#39;Cake&#39;);
$statement->bindValue(2, true);
 
$statement2->bindValue(&#39;:name&#39;, &#39;Pie&#39;);
$statement2->bindValue(&#39;:healthy&#39;, false);

注意使用命名参数的时候你要包含进冒号(:)。PDO还有一个bindParam方法,可以通过引用绑定数值,也就是说它只在语句执行的时候查找相应数值。

现在剩下的唯一要做的事情,就是执行我们的语句:
 

$statement->execute();
$statement2->execute();
 
// Get our results:
$cake = $statement->Fetch();
$pie = $statement2->Fetch();

为了避免只使用bindValue带来的代码碎片,你可以用数组给execute方法作为参数,像这样:
 

$statement->execute(array(1 => &#39;Cake&#39;, 2 => true));
$statement2->execute(array(&#39;:name&#39; => &#39;Pie&#39;, &#39;:healthy&#39; => false));

事务

前面我们已经描述过了什么是事务:

一个事务就是执行一组查询,但是并不保存他们的影响到数据库中。这样做的好处是如果你执行了4条相互依赖的插入语句,当有一条失败后,你可以回滚使得其他的数据不能够插入到数据库中,确保相互依赖的字段能够正确的插入。你需要确保你使用的数据库引擎支持事务。
开启事务

你可以很简单的使用beginTransaction()方法开启一个事务:
 

$db->beginTransaction();
 
$db->inTransaction(); // true!

然后你可以继续执行你的数据库操作语句,在最后提交事务:
 

$db->commit();

还有类似MySQLi中的rollBack()方法,但是它并不是回滚所有的类型(例如在MySQL中使用DROP TABLE),这个方法并不是真正的可靠,我建议尽量避免依赖此方法。

其他有用的选项

有几个选项你可以考虑用一下。这些可以作为你的对象初始化时候的第四个参数输入。

 $options = array($option1 => $value1, $option[..]);
$db = new PDO($dsn, $username, $password, $options);

PDO::ATTR_DEFAULT_FETCH_MODE

你可以选择PDO将返回的是什么类型的结果集,如PDO::FETCH_ASSOC,会允许你使用$result['column_name'],或者PDO::FETCH_OBJ,会返回一个匿名对象,以便你使用$result->column_name

你还可以将结果放入一个特定的类(模型),可以通过给每一个单独的查询设置一个读取模式,就像这样:
 

$query = $db->query(&#39;SELECT * FROM `foods`&#39;);
$foods = $query->fetchAll(PDO::FETCH_CLASS, &#39;Food&#39;);

- 所有读取模式

上面我们已经解释过这一条了,但喜欢TryCatch的人需要用到:PDO::ERRMODE_EXCEPTION。如果不论什么原因你想抛出PHP警告,就使用PDO::ERRMODE_WARNING。

PDO::ATTR_TIMEOUT

当你为载入时间而着急时,你可以使用此属性来为你的查询指定一个超时时间,单位是秒. 注意,如果超过你设置的时间,缺省会抛出E_WARNING异常, 除非 PDO::ATTR_ERRMODE 被改变.

更多属性信息可以在 PHP官网的属性设置 里查看到.
最后的思考

PDO是一个在PHP中访问你的数据库的很棒的方式,可以认为是最好的方式。除非你拒绝使用面向对象的方法或是太习惯 MySQLi 的方法名称,否则没有理由不使用PDO。

更好的是完全切换到只使用预处理语句,这最终将使你的生活更轻松!

相关推荐:

php如何利用PDO访问oracle数据库的方法详解

PHP中关于PDO数据访问抽象层的功能操作的介绍

使用PDO操作MySQL数据库的实例分享(收藏)

以上がPHP PDOの詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。