PHPでのMySQL、MySQLi、PDOの使い方と違い

4958 ワード

MySQLはPHP操作MySQLデータベースの最も原始的なExtensionです.MySQLiのiはImprovementを表し、相対的に進歩的な機能を提供し、Extensionにとってもセキュリティが増加しています.PDO(PHP Data Object)はAbstraction Layerを提供してデータベースを操作しているので、理論的には違いが見えないので、コードを直接見ましょう.
 
まず、MySQLで作成されたコードを見てみましょう.
<?php
mysql_connect($db_host, $db_user, $db_password);
mysql_select_db($dn_name);
$result = mysql_query("SELECT `name` FROM `users` WHERE `location` = '$location'");
while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
    echo $row['name'];
}
mysql_free_result($result);
?>

 
一見問題ないように見えるが、裏には学問がある.
この方式ではBind Columnができず、$locationの場所はSQLに注入されやすい.そしてmysql_が発展しましたescape_string()(備考:5.3.0以降廃棄)およびmysql_real_escape_string()はこの問題を解決しますが、このようにすると、プロセス全体が複雑で醜くなり、パラメータが多ければ、どのような状況になるか想像できます.
<?php
$query = sprintf("SELECT * FROM users WHERE user='%s' AND password='%s'",
mysql_real_escape_string($user),
mysql_real_escape_string($password));
mysql_query($query);
?>

 
MySQLiでは多くの進歩があり、Bind Columnで上記の問題を解決する以外に、Object oriented style(以下のMySQLiの例の書き方)とProcedural style(上のMySQLの例の書き方)の2つの書き方の違いを比較することができます.
<?php
$mysqli = new mysqli($db_host, $db_user, $db_password, $db_name);
$sql = "INSERT INTO `users` (id, name, gender, location) VALUES (?, ?, ?, ?)";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('dsss', $source_id, $source_name, $source_gender, $source_location);
$stmt->execute();
$stmt->bind_result($id, $name, $gender, $location);
while ($stmt->fetch())
{
    echo $id . $name . $gender . $location;
}
$stmt->close();
$mysqli->close();
?>

 
Bind Resultなどの欠点もいくつか発見されましたが、これは少し余計ですが、これは重要ではありません.最大の問題は抽象的な方法ではないので、バックエンドがデータベースを交換するとき、苦痛の始まりです.
そこでPDOが登場しました(注記:現在UbuntuとDebianでは、PDOは直接的なスイートではなく、PECLでインストールする必要があります).
roga@carlisten-lx:~$ pecl search pdo

=======================================
Package Stable/(Latest) Local
PDO 1.0.3 (stable) PHP Data Objects Interface.
PDO_4D 0.3 (beta) PDO driver for 4D-SQL database
PDO_DBLIB 1.0 (stable) FreeTDS/Sybase/MSSQL driver for PDO
PDO_FIREBIRD 0.2 (beta) Firebird/InterBase 6 driver for PDO
PDO_IBM 1.3.2 (stable) PDO driver for IBM databases
PDO_INFORMIX 1.2.6 (stable) PDO driver for IBM Informix INFORMIX databases
PDO_MYSQL 1.0.2 (stable) MySQL driver for PDO
PDO_OCI 1.0 (stable) Oracle Call Interface driver for PDO
PDO_ODBC 1.0.1 (stable) ODBC v3 Interface driver for PDO
PDO_PGSQL 1.0.2 (stable) PostgreSQL driver for PDO
PDO_SQLITE 1.0.1 (stable) SQLite v3 Interface driver for PDO
pdo_user 0.3.0 (beta) Userspace driver for PDO

 
PECLインストールによってインストールされると、次の方法でデータベースを操作できます.
<?php
$dsn = "mysql:host=$db_host;dbname=$db_name";
$dbh = new PDO($dsn, $db_user, $db_password);
$sql = "SELECT `name`, `location` FROM `users` WHERE `location` = ? , `name` = ?";
$sth = $dbh->prepare($sql);
$sth->execute(array($location, $name));
$result = $sth->fetch(PDO::FETCH_OBJ);
echo $result->name . $result->location;
$dbh = NULL; //by www.jbxue.com
?>

 
一見PDOのコードも短くなっていないようですが、メリットは何でしょうか.
1.PDOがデータベースに接続する場合、接続先を接続するデータベースをConnection Stringで決定します.
2、PDOはPDO::setAttributeによって接続時の設定を決定することができ、例えばPersistent Connection、エラーを返信する方式(Exception,E_WARNING,NULL)である.パラメータ名の大文字と小文字を返すなどします.
3、PDOはBind Columnの機能をサポートし、基本的なPrepare、Executeのほかに、Bind単一パラメータを指定し、パラメータタイプを指定することもできる.
4、PDOはAbstraction Layerなので、メディアを交換しても手間がかかるのは比較的少ない.
残念なことに、これらのものは長い間現れていたにもかかわらず、大衆化が足りなかった.皆さんが坊间の本を読むのに惯れているからかもしれないと思いますが、それらの本は往々にして最も简単で伝统的な方法を绍介するだけで、多くの人がMySQLのようなデータベースに直接接続しています.
しかし、個人的にはActiveRecordやPropel ORM(Object-Relational Mapping)のようなDBIでデータベースに接続するのが一番好きです.
たとえばActiveRecordを例にとると、このようなSQL記述を実装する場合は、次のようになります.
INSERT INTO `users` (id, name, gender, location) VALUES(1, 'roga', 'male', 'tpe')

 
PDOでは次のように書かれています.
<?php
$sql = "INSERT INTO `users` (id, name, gender, location) VALUES(?, ?, ?, ?)";
$sth = $dbh->prepare($sql);
$sth->execute(array(1, 'roga', 'male', 'tpe'));
?>

 
しかし、ActiveRecordで言えば、
<?php
$user = new User();
$user->id = 1;
$user->name = 'roga';
$user->gender = 'male';
$user->location = 'tpe';
$user->save();
?>

 
後者は文法的に簡潔ではないでしょうか.SQL言語への依存性も大幅に低下しています.SQLの実装に関する異なるデータベースの問題は、Comparison of different SQL implementationsを参照してください.
 
PHPの中でMySQL、MySQLiとPDOの使い方と区别