【PHP】PDOとは?プリペアドステートメントの使い方とメソッドの種類
この記事からわかること
- PDOの詳細とメリット
- プリペアドステートメントの使い方
- データベース接続の際に使えるメソッドの意味と使い方
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
PHPでのデータベース接続方法の1つにPDOがあります。
PDOを使うことで異なるデータベースに変更になった時にコードを変更しなくても継続して動作させることができます。
今回はPDOのメリットと使い方、そして関連するメソッドをまとめていきたいと思います。
PDOとは?
PDOとはPHP Data Objectsの略称でデータベース抽象型レイヤの1つです。
データベース抽象型レイヤとはデータベースに接続する時にデータベースの種類の違いを気にすることなく接続できるようにしてくれる機能のことになります。
その中でもPDOはPHPにデフォルトで組み込まれているので特に工程を踏むこともなくそのまま使うことができるのがメリットの1つでもあります。
またPDOではプリペアドステートメントという仕組みを使うことで内部的に自動でエスケープ処理を施してくれるためセキュリティ面でも安全に使用することができます。
PDOはデータベース接続を安全かつ移植性を高く行うことができる優れた機能なのです。
PDOのメリットまとめ
- インストールなどの準備がいらない
- データベースの差異を隠蔽してくれる
- セキュリティ面でも安心
PDOでデータベース接続を行う方法
PDOを実際に実行するにはPDOクラスを用いて行います。通常のクラスと同じでインスタンス化して使用し、特有のメソッドや定数が用意されています。
PDOクラスをインスタンス化するタイミングで実際にデータベースとの接続を試みます。成功すれば返り値としてオブジェクトを、失敗すればNULL値
を返します。
データベース接続コード
$dsn = 'mysql:dbname=データベース名;host=localhost;charset=utf8';
$user = 'ユーザーID';
$password ='password';
$dbh = new PDO($dsn,$user,$password);
インスタンス化する際には適切な引数が必要になります。後から修正しやすいように前もって変数に格納して引数に渡すのが定石となっています。
$dbh = new PDO(データベース接続文字列,ユーザ名,パスワード);
引数には「データベース接続文字列」「ユーザー名」「パスワード」を指定します。
データベース接続文字列はデータベースの種類によって異なります。上記のコードはMySQLに接続する時の文字列です。 WordPressやMAMPなどは、MySQLを使用していますのでこのコードさえ覚えておけば大丈夫です。
ちなみに・・・変数名の意味
- $dsn→Data Source Name:データベース接続文字列
- $dbh→Data Base handler:データベースを操作するハンドル(舵)
関連記事:【PHP】class(クラス)の使い方とは?変数やメソッド、インスタンスの意味
WordPressの場合
WordPressの場合に必要となってくるユーザ名とパスワードはphpMyAdminに接続する時に使用するIDとパスワードです。
ユーザ名は「MySQL設定」>「MySQLユーザ一覧」のユーザ部分になります。おそらく「xs012345_wp1」のようになっていると思います。(local_host)の部分は含めずにコピーして貼り付ければOKです。パスはサーバーパネルにログインする時のものと同じものでOKです。
WordPressの接続コード
$dsn = 'mysql:dbname=データベース名;host=localhost;charset=utf8';
$user = 'xs012345_wp1';
$password ='password'; // 自分で設定したパスワード
$dbh = new PDO($dsn,$user,$password);
MAMPの場合
MAMPの場合、ユーザ名とパスワードは「root」に固定されているはずです。
なので変更点はデータベース名のみになります。
MAMPの接続コード
$dsn = 'mysql:dbname=データベース名;host=localhost;charset=utf8';
$user = 'root';
$password ='root';
$dbh = new PDO($dsn,$user,$password);
ちなみにphpMyAdminはMySQLの管理画面ツールなので使っていればデータベースはMySQLということになります。
データベース接続の時の注意点
インスタンス化してデータベース接続をする際には接続が失敗した時に備えた準備をしておくことが重要です。
準備しておくことで修正がしやすくなったり、スクリプトの停止を防いだり、不要な情報や挙動をユーザーに感じさせないようにすることができます。
PDOクラスはデータベース接続に失敗した時にPDOExceptionという例外(エラー)を発生させます。
この例外をtry〜catch(〜finally)命令で捕捉することでエラー後の挙動を操作することができます。
try{
// 例外が発生する可能性のあるコード
$dsn = 'mysql:dbname=データベース名;host=localhost;charset=utf8';
$user = 'ユーザーID';
$password ='password';
$dbh = new PDO($dsn,$user,$password);
// ⇧ここでエラーが発生すると⇩以下は実行されない
// データベース絡みの処理
}catch(PDOException $e){
// 例外発生時の処理
echo $e->getMessage(); // エラー内容を表示
}
finally{
// 例外の有無に関わらす実行されるコード
$dbh = NULL; // エラーの有無に関わらず後処理
}
try〜catch(〜finally)命令の詳しい使い方と例外については⇩こちらをご覧ください
【PHP】Exceptionクラスとは?例外処理の方法とtryブロックの使い方を解説!
try〜catch(〜finally)命令のおかげで接続時にエラーが発生した場合に処理を分岐させることができます。本来では接続後に$dbh
をキーにデータベース絡みの処理を行いますが、失敗した場合は$dbh
にNULL
が格納されているため予期せぬ挙動を招いてしまいます。
失敗時は後続の処理を行わずに即座に処理を切り替え、catchブロックに記述した処理を実行させます。
finallyブロックは例外の有無に関わらす実行されるので後処理として$dbh
を破棄しておきましょう。
データベース処理(SQL)の実行
データベース処理にはSQL文が関わってきます。
SQLとはStructured Query Languageの略称でRDBMS(リレーショナルデータベースマネジメントシステム)のを操作・制御するデータベース言語のことです。
このSQL文を使うことでデータベースから希望の情報にマッチしたデータのみを抜き出すことができます。
データベース処理の流れは以下の通りです。
- SQL文の構築(1行目)
- SQL文の実行⇨結果を取得(2〜3行目)
- 結果からさらに必要な情報を抜き出す(5〜7行目)
サンプルコード
$sql = 'SELECT * FROM post_table WHERE category = php order by entryDay DESC' ;
$stmt = $dbh->query($sql);
while($result = $stmt->fetch(PDO::FETCH_ASSOC)){
echo $result['title'];
}
例えば上のサンプルコードはテーブル名「post_table」の中の「category」列が「php」のデータを登録日「entryDay」列の降順(DESC)に並び替えた記事情報(行)を取得することができます。
関連するメソッドの意味
queryメソッド
$stmt = $dbh->query($sql);
データベースに対してクエリ(SQLによる問い合わせ)を発行するメソッドです。後述しているプレイスホルダがある場合はこのメソッドは使えません。返り値としてテーブルから取得した行にアクセスするためのPDOStatementオブジェクトを返します。
fetchメソッド
$result = $stmt->fetch(PDO::FETCH_ASSOC);
echo $result['title'];
実際に行のデータにアクセスするのはfetchメソッド
の役割です。PDOStatementオブジェクトに格納されているデータから1行だけ取り出して返します。引数にmodeパラメータを指定することで返り値の形を変更することができます。
- FETCH_ASSOC:列名で添字のついた連想配列のみを返す
- FETCH_BOTH (デフォルト):列名で添字のついた連想配列と添字が0から始まる配列両方を返す
fetchメソッドで全ての行を取り出す場合
while($result = $stmt->fetch(PDO::FETCH_ASSOC)){
echo $result['title'];
}
fetchメソッド
で全てのデータを取り出すにはwhile
で繰り返せばOKです。データを読み切ったらfalse
を返すので自動で処理を終了してくれます。
fetchAllメソッド
$result = $stmt->fetchAll();
var_dump($result);
fetchAllメソッド
は1行ずつではなく一度に全てのデータを取り出すメソッドです。引数の指定は先ほどのfetchメソッド
と同じです。
これがプレイスホルダを使わない場合のSQL実行処理の流れになります。プレイスホルダを使用するとコードが変わってきますので注意してください。
プリペアドステートメントの使い方
サンプルコード
$sql = 'SELECT * FROM テーブル名 WHERE descri LIKE :word OR title LIKE :word2' ;
$stmt = $dbh->prepare($sql);
$stmt->bindValue(':word',"%{$S_word}%",PDO::PARAM_STR);
$stmt->bindValue(':word2',"%{$S_word}%",PDO::PARAM_STR);
$stmt->execute();
PDOではプリペアドステートメントという機能を使うことができます。プリペアド(予め、準備された)ステートメント(命令文)から推測できるように予め場所を確保し、そこに値を後から入れ込む流れになっています。
PDOでは後から値を入れ込む際に内部的に自動でエスケープ処理を施してくれます。SQLに絡んだサイバー攻撃の1つSQLインジェクションもこのPDOで防ぐことができます。
関連記事:【絶対必須】phpのセキュリティ対策!XSSとメールヘッダーインジェクションを防ごう
この仕組みはform要素などから渡された入力値を含んだSQL文を実行する時に使用します。
例えば「検索BOX」のように入力された値がタイトル(title)か説明文(descri)に有ればその記事情報を取得するなどといった場合に使うことができます。この場合はデータベースにあらかじめ記事情報を格納しておいてください。では実際にどのように使うのか解説していきます。
関連記事:【完全自作】phpで検索ボックスを作ろう!SQL文と仕組みを詳しく解説!
プレイスホルダとbindValueメソッド
まずSQL文にはプレイスホルダを組み込んで文を構築します。
プレイスホルダとは値を入れ込むための場所 (値)のことです。このプレイスホルダに後から値を追加することでエスケープ処理が施されます。
通常のSQL文にプレイスホルダを記述する時は「:名称
」か「?
」のどちらかで場所を確保します。名称は分かりやすい名前にすればOKです。
どちらのプレイスホルダを使っても良いですがその後のコードが少し変わるので注意してください。
:名称の場合
$sql = 'SELECT * FROM テーブル名 WHERE descri LIKE :word OR title LIKE :word2' ;
? の場合
$sql = 'SELECT * FROM テーブル名 WHERE descri LIKE ? OR title LIKE ?' ;
これで場所の確保は完了です。次に確保した場所に値を入れ込む方法です。その前に$stmt = $dbh->prepare($sql);
をしないといけませんが後述しますのでここでは飛ばします。
値を入れ込むのはbindValueメソッド
の役割です。
bindValueメソッド
$stmt->bindValue($param,$value,$type=PDO::PARAM_STR);
// bindValue(プレイスホルダの値,格納したい値,データ型);
// 「:名称」の場合はそのまま「:名称」と指定
// 「?」の場合は?が何番目にあるかを数字「1」や「2」などで指定する
// $typeは入力値のデータ型を記述する 文字列⇨PARAM_STR 数値⇨PARAM_INT
今回はPOSTなどで受け取った入力値を変数$S_word
に格納したとして記述します。
:名称の場合
$stmt->bindValue(':word',$S_word,PDO::PARAM_STR);
$stmt->bindValue(':word2',$S_word,PDO::PARAM_STR);
? の場合
$stmt->bindValue(1,$S_word,PDO::PARAM_STR);
$stmt->bindValue(2,$S_word,PDO::PARAM_STR);
プレイスホルダに関連するメソッド
prepareメソッド
$stmt = $dbh->prepare($sql);
prepareメソッド
はクエリ(SQLによる問い合わせ)のパースを行うメソッドです。パースとはコードを機械が理解できるように構文の解析を行い変換することを言います。
ここではプレイスホルダを含んだSQL文を実行するための前準備をしているイメージでOKです。
executeメソッド
$stmt->execute();
executeメソッド
が実際にSQL文を実行するメソッドになります。先ほどのqueryメソッド
と同じ役割です。こちらはプレイスホルダを含んでいても実行できます。
PDOに関する他のメソッド
execメソッド
$stmt->execute();
execメソッド
もSQL文を実行するメソッドです。違いとしては返り値として影響した行を数値で返します。データベースのアップデートなど返り値を必要としないSQLの実行に使えます。プレイスホルダは使用できません。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。