【モダンなPHP】PHPでPDOを使ってMySQLに接続する方法!



【モダンなPHP】PHPでPDOを使ってMySQLに接続する方法!

この記事をご覧になっている人は、おそらくPDOの使用方法が分からない、または理解が曖昧なことが多いと思います。PDOはPHP初心者には敷居が高く、複合して覚えなくてはならないことも多く、挫折しやすいです。

この記事では解説を交えながらPDOを使用してMySQLと接続してCRUD操作を行う方法を説明します。

目次
  1. PHPでPDOを使ってMySQLに接続する方法!
  2. PDOとは?
  3. PDOを使ってMySQLに接続
  4. PDOインスタンスを生成する
  5. PDOを使ってCRUD操作を行う
  6. レコードを取得する(SELECT)
  7. レコードを挿入する(INSERT)
  8. レコードを書き換えるする(UPDATE)
  9. レコードを削除する(DELETE)
  10. まとめ
  11. 参考文献

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とは?

images

PDOとは、PHP Data Objectsの略称で、一言で言い表すならば、PHPからデータベースのアクセスを抽象的にしてくれるものです。

抽象的とはどういうことでしょうか。データベースにMySQLやPostgreSQLなど複数種類があります。PHPではmysqliクラスやPostgreSQL関数を使用したりとデータベースごとに関数を使い分けなければなりません。どのデータベースでも、同じ書き方で使用できるようにしたのがPDOです。各データベースのPDOドライバにアクセスしてデータベースを操作します。PHPではPDOドライバを直接呼ぶのではなく、データベース共通のインスタンスを作ります。

初心者には敷居が高いですが、ぜひPDOの公式ドキュメントも読んでみてください。詳細な情報が書かれているので、さらなるステップアップを目指す人には、うってつけのドキュメントです。

PHP: PDO - Manual

PDOを使ってMySQLに接続

images

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操作を行う

images

今回使用するデータベースのuserテーブルの初期のレコードは、以下のようになります。このテーブルに対してCRUD操作を行います。CRUD操作とは何かわからない人はこちらのサイトをご覧ください。

images

レコードを取得する(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"
  }
}

まとめ

images

PDOは、PHPでMySQLを操作するmysqliクラスに比べて、難易度は高いです。しかし、プレースホルダーを使用して値を文字列として処理するので、SQLインジェクションの対策になります。今からノンフレームワークのPHPアプリケーションを作るのであれば、PDOの使用はセキュリティ面で常識となっています。クラスやインスタンスの概念が理解でき、他に理由がないのであれば、PDOを使うべきです。もし、この記事だけで理解できない場合は、PDOの公式ドキュメントを見てみるといいでしょう。網羅的に情報が書かれており、サンプルコードも豊富です。PDOを使いこなすには、実際に手を動かしながら触ってみるのが上達への近道です。

参考文献

「PHP逆引きレシピ 第二版」鈴木憲治、山田 直明、山本義之、浅野仁、櫻井 雄大、安藤建一、著、翔泳社、2013

PHP: PDO - Manual

PHP: PDO_MYSQL DSN - Manual

PHP: プリペアドステートメントおよびストアドプロシージャ - Manual

PHP: PDO::prepare - Manual

PHP: PDOStatement::bindValue - Manual

PHP: PDOStatement::execute - Manual

PHP: PDOStatement::fetchAll - Manual

PHP: 定義済み定数 - Manual

PDOの利用 | PHP Labo

MySQLへの接続 - PHP入門

PDOでMySQLに接続からINSERTやSELEC、UPDATEからDELETE、SUM、COUNTやテーブル作成など|LABO IWASAKI

PHP5.1.0から導入されたPHP Data Objects (PDO) 拡張モジュールとPDOクラス(データベース接続) - ts0818のブログ

山川竜太郎
この記事を書いた人
山川竜太郎
\ 無料体験開催中!/自分のペースで確実に習得!
オンライン・プログラミングレッスンNo.1のCodeCamp