- 公開日: 2018年12月27日
【モダンなPHP】PHPでPDOを使ってMySQLに接続する方法!
この記事をご覧になっている人は、おそらくPDOの使用方法が分からない、または理解が曖昧なことが多いと思います。PDOはPHP初心者には敷居が高く、複合して覚えなくてはならないことも多く、挫折しやすいです。
この記事では解説を交えながらPDOを使用してMySQLと接続してCRUD操作を行う方法を説明します。
PHPでPDOを使ってMySQLに接続する方法!
当記事は以下の環境にて検証しています。
- Mac OS X 10.12.4
- PHP 7.1.16
- MySQL 5.7.21
PDOの使用は前提知識として、「PHPでクラスとインスタンスの概念が理解できる」「PHPとMySQLの接続ができる」ことが求められるので、初心者には少し難しいかもしれません。PHPのクラスの概念が分からない人は、公式ドキュメントを見ると助けになってくれます。PHPとMySQLの接続ができていない方はこちらを参考にして環境構築してください。
PDOとは?
PDOとは、PHP Data Objectsの略称で、一言で言い表すならば、PHPからデータベースのアクセスを抽象的にしてくれるものです。
抽象的とはどういうことでしょうか。データベースにMySQLやPostgreSQLなど複数種類があります。PHPではmysqli
クラスやPostgreSQL
関数を使用したりとデータベースごとに関数を使い分けなければなりません。どのデータベースでも、同じ書き方で使用できるようにしたのがPDOです。各データベースのPDOドライバにアクセスしてデータベースを操作します。PHPではPDOドライバを直接呼ぶのではなく、データベース共通のインスタンスを作ります。
初心者には敷居が高いですが、ぜひPDOの公式ドキュメントも読んでみてください。詳細な情報が書かれているので、さらなるステップアップを目指す人には、うってつけのドキュメントです。
PDOを使ってMySQLに接続
PDOを使ってPHPとMySQLを接続するには、PDOクラスを使用します。
PDOインスタンスを生成する
PDOはPHP5.1移行にはPHPをインストールした時点で使用可能な状態にあります。MySQLのPDOドライバにアクセスするためにPDOクラスを使用してPDOインスタンスを生成してみましょう。PDOクラスは、PHPとデータベースサーバーの間の接続を行うクラスです。
サンプルコード
PDOインスタンスを生成して、MySQLの接続を行うサンプルソースです。ローカルホスト内にあるshop
という名前のデータベースにアクセスします。
PDO
クラスのコンストラクタの書式は以下の通りです。
PDO::__construct($dsn,$username,$password,$option)
引数 | 属性 | パラメータ |
---|---|---|
$dsn | string | データソース名またはDSN |
$username(任意) | string | データベースのユーザー名 |
$password(任意) | string | ユーザーのパスワード |
$options(任意) | array | ドライバ固有の接続オプション、今回は使用しない |
$dsn
は、mysql:host=[データベースサーバーのホスト名]:dbname=[データベース名]
の形式で記述してください。その他のパラメータについては公式ドキュメントをご覧ください。コンストラクタの引数については、ご自身の環境に合わせたものに適宜読み替えてください。
pdo_connect.php
<?php
// ドライバ呼び出しを使用して MySQL データベースに接続します
$dsn = 'mysql:dbname=shop;host=127.0.0.1';
$user = 'root';
$password = 'root';
try {
$dbh = new PDO($dsn, $user, $password);
echo "接続成功\n";
} catch (PDOException $e) {
echo "接続失敗: " . $e->getMessage() . "\n";
exit();
}
// 素敵な処理
出力結果
$ php pdo_connect.php
接続成功
接続設定が正常だと、「接続成功」と出力され、$dbh
にPDOインスタンスが生成されます。
接続失敗時には、PDOException
例外がスローされます。以下の出力がデータベース名が見つからない場合のエラーメッセージです。
$ php pdo_connect.php
接続失敗: SQLSTATE[HY000] [1049] Unknown database 'DB'
PDOを使ってCRUD操作を行う
今回使用するデータベースのuser
テーブルの初期のレコードは、以下のようになります。このテーブルに対してCRUD操作を行います。CRUD操作とは何かわからない人はこちらのサイトをご覧ください。
レコードを取得する(SELECT)
まずは、SELECT
処理を実行してみましょう。
SELECT
文の処理を行うには、PDOStatement
クラスを使用します。このクラスはプリペアドステートメントを表します。プリペアドステートメントとは、類似のSQLを関数にして値を引数として使用することです。
プリペアドステートメントとはいったい何の ことでしょう? これは、実行したい SQL をコンパイルした 一種のテンプレートのようなものです。パラメータ変数を使用することで SQL をカスタマイズすることが可能です。
ここから初めて出てくる関数が増えるので、表にしてまとめました。関数の役割がわからなくなったら、公式ドキュメントを確認しましょう!
関数 | 関数の役割 |
---|---|
PDO::prepare() | PDOStatement::execute() 関数によって実行されるSQLステートメントを準備する。 |
PDOStatement::bindValue() | プリペアドステートメントで使用するSQL文の中で、 プレースホルダに値をバインドする。 |
PDOStatement::execute() | プリペアドステートメントを実行する。 |
PDOStatement::fetchAll() | 全ての結果行を含む配列を返す。 |
また、PDOクラスには、定義済み定数が宣言されています。これをPDOStatement::bindValue()
関数やPDOStatement::fetchAll()
関数などで引数として与えて、関数の制御を指定します。1つの記事で全て説明するのは困難なので、一部のみ掲載します。この他にも知りたい場合は、公式ドキュメントをご覧ください。
定数 | 説明 |
---|---|
PDO::PARAM_INT | PDOStatement::bindValue() 関数で使用される。データベースのデータ型をINTEGER型として指定する。 |
PDO::PARAM_STR | PDOStatement::bindValue() 関数で使用される。データベースのデータ型をCHAR, VARCHAR, または他の文字列データ型として指定する。 |
PDO::FETCH_NUM | PDOStatement::fetchAll() 関数やPDOStatement::fetch() 関数で使用される。クエリ結果を数値添え字配列として返す。 |
PDO::FETCH_ASSOC | PDOStatement::fetchAll() 関数やPDOStatement::fetch() 関数で使用される。クエリ結果を連想配列として返す。 |
pdo_select.php
<?php
// 先ほど作成したPDOインスタンス作成をそのまま使用します
require 'pdo_connect.php';
// SQL文を準備します。「:id」がプレースホルダーです。
$sql = 'SELECT * FROM user WHERE id < :id';
// PDOStatementクラスのインスタンスを生成します。
$prepare = $dbh->prepare($sql);
// PDO::PARAM_INTは、SQL INTEGER データ型を表します。
// SQL文の「:id」を「3」に置き換えます。つまりはidが3より小さいレコードを取得します。
$prepare->bindValue(':id', 3, PDO::PARAM_INT);
// プリペアドステートメントを実行する
$prepare->execute();
// PDO::FETCH_ASSOCは、対応するカラム名にふられているものと同じキーを付けた 連想配列として取得します。
$result = $prepare->fetchAll(PDO::FETCH_ASSOC);
// 結果を出力
var_dump($result);
出力結果
$ php pdo_select.php
接続成功
array(2) {
[0]=>
array(2) {
["id"]=>
string(1) "1"
["name"]=>
string(4) "sato"
}
[1]=>
array(2) {
["id"]=>
string(1) "2"
["name"]=>
string(7) "musashi"
}
}
サンプルコードを一通り読んでみて一連の処理の流れは掴めたと思います。次は、このテーブルに対してレコードをINSERTを行います。
レコードを挿入する(INSERT)
INSERTする場合でも、先ほどのSELECTの場合と処理の内容は同じです。ここでは、idが4、nameがkobayashiのレコードを追加します。
pdo_insert.php
<?php
require 'pdo_connect.php';
// SQL文を準備します。「:id」「:name」がプレースホルダーです。
$sql = 'INSERT INTO user (id, name) VALUE (:id, :name)';
$prepare = $dbh->prepare($sql);
$prepare->bindValue(':id', 4, PDO::PARAM_INT);
$prepare->bindValue(':name', 'kobayashi', PDO::PARAM_STR);
$prepare->execute();
// INSERTされたデータを確認します
$sql = 'SELECT * FROM user';
$prepare = $dbh->prepare($sql);
$prepare->execute();
$result = $prepare->fetchAll(PDO::FETCH_ASSOC);
var_dump($result);
出力結果
$ php pdo_insert.php
接続成功
array(4) {
[0]=>
array(2) {
["id"]=>
string(1) "1"
["name"]=>
string(4) "sato"
}
[1]=>
array(2) {
["id"]=>
string(1) "2"
["name"]=>
string(7) "musashi"
}
[2]=>
array(2) {
["id"]=>
string(1) "3"
["name"]=>
string(8) "takeuchi"
}
[3]=>
array(2) {
["id"]=>
string(1) "4"
["name"]=>
string(9) "kobayashi"
}
}
レコードを書き換えるする(UPDATE)
UPDATEでは、先ほどINSERTしたレコードに対して、nameをkikuchiに変更します。
pdo_update.php
<?php
require 'pdo_connect.php';
// SQL文を準備します。「:id」「:name」がプレースホルダーです。
$sql = 'UPDATE user SET name=:name WHERE id=:id';
$prepare = $dbh->prepare($sql);
$prepare->bindValue(':id', 4, PDO::PARAM_INT);
$prepare->bindValue(':name', 'kikuchi', PDO::PARAM_STR);
$prepare->execute();
// UPDATEされたデータを確認します
$sql = 'SELECT * FROM user';
$prepare = $dbh->prepare($sql);
$prepare->execute();
$result = $prepare->fetchAll(PDO::FETCH_ASSOC);
var_dump($result);
出力結果
$ php pdo_update.php
接続成功
array(4) {
[0]=>
array(2) {
["id"]=>
string(1) "1"
["name"]=>
string(4) "sato"
}
[1]=>
array(2) {
["id"]=>
string(1) "2"
["name"]=>
string(7) "musashi"
}
[2]=>
array(2) {
["id"]=>
string(1) "3"
["name"]=>
string(8) "takeuchi"
}
[3]=>
array(2) {
["id"]=>
string(1) "4"
["name"]=>
string(7) "kikuchi"
}
}
レコードを削除する(DELETE)
最後はDELETEです。INSERTされたレコードを削除します。
pdo_delete.php
<?php
require 'pdo_connect.php';
// SQL文を準備します。「:id」がプレースホルダーです。
$sql = 'DELETE FROM user WHERE id=:id';
$prepare = $dbh->prepare($sql);
$prepare->bindValue(':id', 4, PDO::PARAM_INT);
$prepare->execute();
// DELETEされたデータを確認します
$sql = 'SELECT * FROM user';
$prepare = $dbh->prepare($sql);
$prepare->execute();
$result = $prepare->fetchAll(PDO::FETCH_ASSOC);
var_dump($result);
出力結果
$ php pdo_delete.php
接続成功
array(3) {
[0]=>
array(2) {
["id"]=>
string(1) "1"
["name"]=>
string(4) "sato"
}
[1]=>
array(2) {
["id"]=>
string(1) "2"
["name"]=>
string(7) "musashi"
}
[2]=>
array(2) {
["id"]=>
string(1) "3"
["name"]=>
string(8) "takeuchi"
}
}
\Webサイト担当者としてのスキルが身に付く/
まとめ
PDOは、PHPでMySQLを操作するmysqli
クラスに比べて、難易度は高いです。しかし、プレースホルダーを使用して値を文字列として処理するので、SQLインジェクションの対策になります。今からノンフレームワークのPHPアプリケーションを作るのであれば、PDOの使用はセキュリティ面で常識となっています。クラスやインスタンスの概念が理解でき、他に理由がないのであれば、PDOを使うべきです。もし、この記事だけで理解できない場合は、PDOの公式ドキュメントを見てみるといいでしょう。網羅的に情報が書かれており、サンプルコードも豊富です。PDOを使いこなすには、実際に手を動かしながら触ってみるのが上達への近道です。
参考文献
「PHP逆引きレシピ 第二版」鈴木憲治、山田 直明、山本義之、浅野仁、櫻井 雄大、安藤建一、著、翔泳社、2013
PHP: プリペアドステートメントおよびストアドプロシージャ - Manual
PHP: PDOStatement::bindValue - Manual
PHP: PDOStatement::execute - Manual
PHP: PDOStatement::fetchAll - Manual
PDOでMySQLに接続からINSERTやSELEC、UPDATEからDELETE、SUM、COUNTやテーブル作成など|LABO IWASAKI
PHP5.1.0から導入されたPHP Data Objects (PDO) 拡張モジュールとPDOクラス(データベース接続) - ts0818のブログ
- この記事を書いた人
- 山川竜太郎