はじめに
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 を除いて、すべてのステートメントと変数は一目瞭然です。 DSN はデータ ソース名を指し、複数の入力タイプがあります。最も一般的なものは、先ほど使用したものです。PHP 公式 Web サイトでは、他の利用可能な DSN について説明しています。
DSN の他の追加パラメーターを省略し、(mysql:) のようにデータベース ドライバーの後にコロンを置くだけで済みます。この場合、PDO はローカル データベースへの接続を試みます。 MySQLi を使用する場合と同様に、クエリでデータベース名を指定する必要があります。
最後に注意する必要があるのは、初期化オブジェクトを try-catch ブロックでラップしていることです。 PDOException は、クエリが失敗した場合ではなく、PDO 接続が失敗した場合にスローされます。必要に応じて、次のコード $db=line を使用して例外モードを選択できます。
または、PDO の初期化中にパラメータを直接渡すこともできます:
現在使用している方法は間違っており、失敗したときに false を返すだけです。例外を処理しない理由はありません。
基本的なクエリ
PDO で query メソッドと exec メソッドを使用すると、データベース クエリが非常に簡単になります。クエリ結果の行数を取得する場合、exec は非常に使いやすいため、SELECT クエリ ステートメントに非常に役立ちます。
次に、以下の例を使用して両方の方法を見てみましょう:
クエリが正しいと仮定すると、$foods は PDO ステートメント オブジェクトになり、これを使用して結果を取得したり、このクエリで見つかった結果セットの数を確認したりできます。
行数
欠点は、PDO が返される行数を計算するための統一された方法を提供していないことです。 PDO ステートメントには rowCount というメソッドが含まれていますが、このメソッドはすべての SQL ドライバーで動作することが保証されていません (幸いなことに、Mysql データベースでは動作します)。
SQL ドライバーがこのメソッドをサポートしていない場合は、2 つのオプションもあります。セカンダリ クエリ (SELECT COUNT(*)) を使用するか、単純なカウント ($foods) を使用して行数を取得します。
幸いなことに、MySQL の例では、次の簡単な方法を使用して正しい行数を出力できます。
結果セットをトラバースする
これらのおいしいおやつをプリントアウトするのはまったく難しいことではありません:
唯一注意すべき点は、PDO は Fetch メソッドもサポートしているということです。このメソッドは最初の結果のみを返すため、1 つの結果セットのみをクエリする場合に非常に役立ちます。
ユーザー入力をエスケープする (特殊文字)
ユーザーが安全なデータを入力することを保証するために使用される (mysqli_) real_escape_string について聞いたことがありますか。 PDO には、入力文字列内の引用符内の特殊文字をエスケープできる quote と呼ばれるメソッドが用意されています。
エスケープ後、最終的に次の結果が得られます:
前述したように、exec() メソッドを使用して UPDATE、DELETE、INSERT 操作を実装できます。実行後、影響を受ける行の数が返されます。
リーリー
準備されたステートメント
exec メソッドとクエリは依然として PHP で広く使用されサポートされていますが、PHP 公式 Web サイトでは依然として、代わりに準備されたステートメントを使用することを全員に要求しています。なぜ?主な理由は、そのほうが安全だからです。準備されたステートメントは実際のクエリにパラメーターを直接挿入しないため、潜在的な SQL インジェクションの多くが回避されます。ただし、何らかの理由で、PDO は実際には前処理を使用せず、SQL サーバーに渡す前に前処理をシミュレートしてステートメントにパラメータ データを挿入します。これにより、一部のシステムでは SQL インジェクションが発生しやすくなります。
SQL サーバーが実際には前処理をサポートしていない場合は、次のように PDO の初期化中にパラメータを渡すことで、この問題を簡単に解決できます。
リーリー
最初の準備されたステートメントから始めましょう:
$statement = $db->prepare('SELECT * FROM foods WHERE `name`=? AND `healthy`=?'); $statement2 = $db->prepare('SELECT * FROM foods WHERE `name`=:name AND `healthy`=:healthy)';
正如你所见,有两种创建参数的方法,命名的与匿名的(不可以同时出现在一个语句中)。然后你可以使用bindValue来敲进你的输入:
$statement->bindValue(1, 'Cake'); $statement->bindValue(2, true); $statement2->bindValue(':name', 'Pie'); $statement2->bindValue(':healthy', false);
注意使用命名参数的时候你要包含进冒号(:)。PDO还有一个bindParam方法,可以通过引用绑定数值,也就是说它只在语句执行的时候查找相应数值。
现在剩下的唯一要做的事情,就是执行我们的语句:
$statement->execute(); $statement2->execute(); // Get our results: $cake = $statement->Fetch(); $pie = $statement2->Fetch();
为了避免只使用bindValue带来的代码碎片,你可以用数组给execute方法作为参数,像这样:
$statement->execute(array(1 => 'Cake', 2 => true)); $statement2->execute(array(':name' => 'Pie', ':healthy' => 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将返回的是什么类型的结果集,如PDO::FETCH_ASSOC,会允许你使用$result['column_name'],或者PDO::FETCH_OBJ,会返回一个匿名对象,以便你使用$result->column_name
你还可以将结果放入一个特定的类(模型),可以通过给每一个单独的查询设置一个读取模式,就像这样:
$query = $db->query('SELECT * FROM `foods`'); $foods = $query->fetchAll(PDO::FETCH_CLASS, 'Food'); <strong>PDO::ATTR_ERRMODE<br /></strong>
上面我们已经解释过这一条了,但喜欢TryCatch的人需要用到:PDO::ERRMODE_EXCEPTION。如果不论什么原因你想抛出PHP警告,就使用PDO::ERRMODE_WARNING。
PDO::ATTR_TIMEOUT
当你为载入时间而着急时,你可以使用此属性来为你的查询指定一个超时时间,单位是秒. 注意,如果超过你设置的时间,缺省会抛出E_WARNING异常, 除非 PDO::ATTR_ERRMODE 被改变.
更多属性信息可以在 PHP官网的属性设置 里查看到.
最后的思考
PDO是一个在PHP中访问你的数据库的很棒的方式,可以认为是最好的方式。除非你拒绝使用面向对象的方法或是太习惯 MySQLi 的方法名称,否则没有理由不使用PDO。
更好的是完全切换到只使用预处理语句,这最终将使你的生活更轻松!