2018年11月9日(金)/ 2018年11月10日(土)/ PHP

PHP は SQL などのデータベースに接続するのに適したプログラミング言語として Web サイトで重宝されています。
元々は動的な Web ページを生成するために作られ、データベースへの接続する機能を組み込んで誕生しました。

そんな PHP では従来、”mysql_connect” や “mysql_query” などといった関数で MySQL と連携していましたが、PHP5.5 以降では非推奨関数に指定され使用すべきでない手法となりました。
PHP7 以降では “mysql_***” という関数自体も削除されて完全に使用できません。

現在では PDO (PHP Data Objects) と呼ばれるデータベース接続専用のインターフェースが定義され供給されています。
この PDO のお陰でデータベースサーバの種類に依らず同じ構文でデータベースへの接続をすることができます。
そこで今回はそんな PDO によるデータベースへの接続方法などを簡単にまとめます。


スポンサーリンク

とりあえずデータベースに接続してみよう!

何はともあれ、PHP からとりあえず適当なデータベースを用意して接続してみましょう。
MySQL 以外は使ったことが殆どないので MySQL 前提です。

ログイン情報は以下とします。

  • MySQL
  • データベースサーバ : mysql.hogehoge.com
  • ユーザ名 : hoge
  • パスワード : fuga123
  • データベース名:test_db
  • テーブル名:test_table
$pdo = new PDO('mysql:host=mysql.hogehoge.com;charset=utf8mb4', 'hoge', 'fuga123');

PDO クラスを new でインスタンス化するだけです。とても簡単ですね。

PDO の第1引数にはどのサーバに接続するか、どの文字コードを使用するかを指定します。
“host=” に続くホスト名はIPアドレスや “localhost” などでも構いません。
“charset=” には “utf8mb4” を指定しておけば全角文字や絵文字など (4バイト文字) も扱えます。

接続エラーに対する処置

サーバへの接続が必ずしも成功するとは限りませんので、エラー時の対応を処置しておきましょう。
これには、try{}catch(){} 構文を使います。

try{
	$pdo = new PDO('mysql:host=mysql.hogehoge.com;dbname=DB名;charset=utf8mb4', 'hoge', 'fuga123');
} catch(PDOException $err){
	header('Content-Type: text/plain; charset=UTF-8', true, 500);
	exit($err->getMessage());
}

“PDOException” というのは PDO クラスが発生するエラーを表すクラスです。
catch 文で PDO のエラーを $err 変数に入れてエラーメッセージを表示して終了させます。

HTTP ヘッダに応答コード500を指定することでサーバ側のエラーであることをブラウザに伝えておくと良いでしょう。

宣言と同時にデータベースも選択する

ちなみにですが、この宣言と同時にデータベースへの接続も同時に行うことができます。
“dbname=DB名;” を第1引数に追加すればよいです。

$pdo = new PDO('mysql:host=mysql.hogehoge.com;dbname=test_db;charset=utf8mb4', 'hoge', 'fuga123');

PDO について書かれている記事の殆どが宣言と同時にデータベースも指定しているのですが、未指定でも大丈夫です。
(もちろん後から選択します)

データベースを操作しよう!

では、早速データベースを操作していきます。

使用するデータベースの選択

まずは、使うデータベースを選択します。
PDO を宣言した時に指定してあるのであれば改めて選択する必要はありません。

PDO で SQL 文を実行するには query メソッドを使います。
query メソッドでは PHP の変数などを使わない処理を実行する際に使います。

※変数を組み込みたい場合に変数展開で query メソッドを使うのはセキュリティ的にあまり勧められないので固定された SQL 文を実行したい場合だけにした方が良いです。
・参考 → Wikipedia – SQLインジェクション

$pdo->query('USE test_db');

これで “test_db” というデータベースが選択されます。

データベースからデータを取り出す

データベースですからデータを取り出してなんぼです。

データを取り出すには SQL 文では “SELECT” を使います。
とりあえずテーブル内の全件を取得してみます。

$table = $pdo->query('SELECT * FROM test_table');

これで SQL で実行した結果が $table 変数に格納されます。

SQL の結果は PDOStatement というインスタンスの形で返ってきて、そのまま配列のようには扱うことはできません。
しかし、Traversable というインターフェースが実装されているので foreach 関数で結果行を1行ずつ受け取り実行できます。

foreach($table as $row){
	echo var_dump($row), "\n";
}

このように実行すると SQL の結果が行ごとに表示されます。
$row にはテーブルの列名を添字にした連想配列が代入されています。

しかし、いつでも foreach 関数で実行したいわけではないですよね。
そんな時は fetchAll メソッドで配列に変換します。(fetch メソッドもあります)

$table  = $pdo->query('SELECT * FROM test_table');
$result = $table->fetchAll();
echo var_dump($result);

これで結果が配列の形で $result 変数に代入されました。
配列は2次元配列で $result[行][列名] で利用できます。

ちなみにですが、fetchAll の引数を省略すると結果の配列は列名以外にも列番号でも取り出すことができます。
列名だけで良いなら引数に “PDO::FETCH_ASSOC” を指定して下さい。
(無駄にメモリを使う必要もないので “PDO::FETCH_ASSOC” が良いです)

※省略するとデフォルト値の “PDO::FETCH_BOTH” と見なされます。
 ”PDO::FETCH_BOTH” では列名だけの “PDO::FETCH_ASSOC” と列番号だけの “PDO::FETCH_NUM” を合わせたように配列が作られます。

$table  = $pdo->query('SELECT * FROM test_table');
$result = $table->fetchAll(PDO::FETCH_ASSOC);
echo var_dump($result);

PHPの変数を使用して検索結果を取得する

最後に PHP の変数などを利用して SQL 文を動的に変更してデータベース内から情報を検索してみましょう。
query メソッドでも変数展開や文字列の連結などで変数を組み込むことができますが、SQLインジェクションなどの攻撃もありますので以下の方法を使うようにして下さい。

$id = (int)filter_input(INPUT_GET, 'id');
$table  = $pdo->prepare('SELECT * FROM test_table id=:id');
$table->bindValue(':id', $id, PDO::PARAM_INT);
$table->execute();
$result = $table->fetchAll(PDO::FETCH_ASSOC);
echo var_dump($result);

この方法では prepare メソッドで実行する SQL 命令文の元になる文字列を登録します。
prepare を実行しても即時に SQL が実行されることはありません。

次に bindValue メソッドで変数を先ほどの SQL 分の中に組み込んでいきます。
prepare メソッド内で “:任意の文字列” で指定した箇所を bindValue で置換することになります。

また、bindValue の第1引数では “:” を省略することもできます。
prepare 中の “:任意の文字列” を “?” に置き換えると先頭からの順番の数字で指定することもできます。
が、分かりにくいので “:任意の文字列” で統一した方が分かりやすいです。
(コードをコンパクトにする必要があればこれらの方法も十分有用です)

ここで bindValue の第3引数に謎の文字列が指定してありますが、これはデータの型を示します。
指定しないと文字列を表す “PDO::PARAM_STR” と見なされます。
文字列なら省略しても良いですが、明示しておくと分かりやすいと思います。

変数も適切な型にキャスト (型変換) してデータ型も明示するとデータベースに掛かる負荷が下がります。

$table  = $pdo->prepare('SELECT * FROM test_table id=:id');   // こっちの":"は省略できない
$table->bindValue('id', $id, PDO::PARAM_INT);   // ":"を省略できる
$table->execute();

$table  = $pdo->prepare('SELECT * FROM test_table id1=? id2=?');
$table->bindValue(1, $id1, PDO::PARAM_INT);   // prepareで"?"を使うと番号で指定できる
$table->bindValue(2, $id2, PDO::PARAM_INT);   // "?"の場合の番号は1から始まる
$table->execute();

そして最後に execute メソッドで SQL 文を実行します。
実行結果は先ほどと同じように foreach や fetchAll などで取得します。

このようにちょっと面倒ですが bindValue を使う方法だと PDO が SQL 文に適した安全な形に型変換・エスケープしてくれるので SQL インジェクションなどに対してより安全となります。

まとめ

以上、PDO によるデータベースへの接続を簡単にまとめました。

とりあえず PDO 使いたいけど色んな解説記事は難しすぎる・・・という方の参考になれば幸いです。

(参考) もっと詳しいまとめ記事

Qiita さんの以下記事が詳しくまとめられているのでちゃんとやりたい方は以下をどうぞ。

入力したメールアドレスは公開されません。


以下のタグが使用可能です :
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>



このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください