PDO
PDO(プリペアドステートメント)を使用してデータベースにアクセスするのは、結構安全らしい。
…ということで、まとめてみる。
※PCでの閲覧推奨。スマホは変なとこで改行するから間違えちゃうかも。
覚えないで、利用方法だけ知っておく。
- 1: PDOで接続(connect)
- 2: PDOで作成(create)
- 3: PDOで挿入(insert)
- 4: PDOで変更(update)
- 5: PDOで参照(select)
- 6: PDOで削除(delete)
- 7: PDOで抹消(drop)
- 8: 総括
- 1: PDOで接続する(DSN)
- PDOでMySQLに接続。
Data Source Name(データソースネーム) - // PDO接続の基本
try {
$pdo = new PDO(
'mysql:host=ホスト名;dbname=DB名;
charset=utf8', 'ユーザー名', 'パスワード',
array( PDO::ATTR_EMULATE_PREPARES=> false));
} catch (PDOException $e) {
exit('データベース接続失敗。'.$e->getMessage());
} -
赤文字だけ要変更。
$pdoは、以降で使用する。
catch で接続できなかった時は、エラーメッセージを表示
コレが基本みたいだけど、覚えるなら次のを。
覚えませんけどね。 - PDO::ATTR_EMULATE_PREPARES
PHP5.2以降はデフォ。設定不要。
プリペアドステートメントは2回アクセスするため、要設定!
include_once("URI"); で設定を入れておけば、とても幸せ。
define は、要変更!
(私はこれを雛形にします:コピペ用) -
[データベースが無い時]
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '1234');
$option = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// デフォルトのエラー発生時の処理方法を指定
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
// SELECT 等でデータを取得する際の型を指定
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
// SELECT した行数を取得する関数 rowCount() が使える
PDO::ATTR_EMULATE_PREPARES => false,
// MySQLネイティブのプリペアドステートメント機能の代わりにエミュしたものを使う設定
PDO::ATTR_STRINGIFY_FETCHES => false
// 取得時した内容を文字列型に変換するかのオプション,int型も文字列扱い
);
$dsn = 'mysql: host=' . DB_HOST . ';charset=utf8';
try {
$pdo = new PDO($dsn, DB_USER, DB_PASS, $option);
} catch (PDOException $e){
echo $e->getMessage();
} -
[データベースが有る時]
define('DB_HOST', 'localhost');
define('DB_USER', 'root');
define('DB_PASS', '1234');
define("DB_NAME","database");
$option = array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
// デフォルトのエラー発生時の処理方法を指定
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
// SELECT 等でデータを取得する際の型を指定
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true,
// SELECT した行数を取得する関数 rowCount() が使える
PDO::ATTR_EMULATE_PREPARES => false,
// MySQLネイティブのプリペアドステートメント機能の代わりにエミュしたものを使う設定
PDO::ATTR_STRINGIFY_FETCHES => false
// 取得時した内容を文字列型に変換するかのオプション,int型も文字列扱い
);
$dsn = 'mysql:dbname='.DB_NAME.';host=' . DB_HOST . ';charset=utf8';
try {
$pdo = new PDO($dsn, DB_USER, DB_PASS, $option);
} catch (PDOException $e){
echo $e->getMessage();
}
- 2: create文
- データベースやテーブルを作成
- こちらも雛形っぽくしているけど、型を決めないといけないので要アレンジ
-
// Database作成
// データベース名:bbs を追加
define("DB_NAME","bbs");
$sql= sprintf('create database if not exists %s default character set utf8;',DB_NAME);
$res= $pdo -> prepare($sql);
$res -> execute(); -
$sql でsql文を作成。
実行だけすれば良いが、自分の中で手法を統一させるために、あえて$resを使用。
sql文を prepareに入れて、接続していた$pdoでアクセス。
この際にシングルアローを使用する。
sql文の実行は、 execute()を使用する。
if not existsは、同じデータベース名がなければ作成という制御。
default character set utf8;で文字コードを指定。 - データベースを作成したら、要再接続!
その際には下記を付与。 -
// Database作成時の再接続
// nullで接続を切断
$pdo = null;
$dsn = 'mysql:dbname='.DB_NAME.';host=' . DB_HOST . ';charset=utf8';
try {
$pdo = new PDO($dsn, DB_USER, DB_PASS, $option);
} catch (PDOException $e){
echo $e->getMessage();
} -
$pdo を nullにすることで接続を終了。
DB_NAMEは既に定数化しているので、そのまま使用。 -
// Table作成
$sql1= 'create table if not exists users(
user_id int not null auto_increment,
user_name varchar(255) not null,
password char(32) not null,
primary key(user_id),
unique(user_name)
)character set utf8;';
$res1= $pdo -> prepare($sql1);
$res1 -> execute();
-
後で主キー追加設定 -> create table users(primary kye(user_id));
空白ダメ -> not null
主キー -> primary key(カラム名);
ユニーク -> unique(カラム名);
auto_increment はカラムに1つだけ。
ここでも文字コードを指定しておく。 -
$sql2= 'create table if not exists texts(
id int not null auto_increment,
name varchar(255) not null,
text varchar(500),
primary key(id)
)character set utf8;';
$res2 = $pdo -> prepare($sql2);
$res2 -> execute();
- 3: insert文
- PDOでデータをINSERTする
プリペアドステートメントで挿入
"test1"を"users"に追加する -
// tableにinsertする
$sql = $pdo -> prepare("INSERT INTO users (user_name, password) VALUES (:name, :pass)");
$sql-> bindParam(':name', $name, PDO::PARAM_STR);
$sql->bindParam(':pass', $pass, PDO::PARAM_STR);
//$sql->bindValue(':value', $value, PDO::PARAM_INT);
$name = 'test1';
$pass = md5('1234');
$sql->execute(); - $sql->bindParam('ここにbindする変数', 変数, PDO::PARAM_STR);
- sprintfでの%sや%dの代わりにbindを使用する。
● bindParamは PDO::PARAM_INT を指定しても 文字列として扱われる
● bindValue は値の指定を変数でも行えるし、数値を指定する事も可能
この場合は PDO::PARAM_INT などの型指定が必要。
- 4: update文
-
PDOでデータをINSERTする
プリペアドステートメントで挿入 -
// insertした"test1"を"test2"に変更
$sql = $pdo -> prepare(
"UPDATE users SET user_name= :name , password= :pass where user_name='test1';"
);
$sql->bindParam(':name', $name, PDO::PARAM_STR);
$sql->bindParam(':pass', $pass, PDO::PARAM_STR);
$name = 'test2';
$pass = md5('1111');
$sql->execute(); -
● insertとほぼ一緒。
結局は覚えることって少ないのかも…
と、ここで気付き始めました。
そして気合を入れてPHP_Manualを見てみたら…
メチャ多くて、再度覚えることを諦めました(苦笑)
先生じゃないんだから、使えたらいいんだよ。うん。
- 5: select文
-
これはちょっと違うので注意。
でも、一番使うと思うので覚えますね。きっと。 -
// PDOでデータをselectする
// $pdo->query("SELECT * FROM テーブル名 WHERE 条件文 ORDER BY 条件");
$sql = $pdo -> query("SELECT * FROM users;");
while($row = $sql -> fetch(PDO::FETCH_ASSOC)) {
$id = $row["user_id"];
$user = $row["user_name"];
$pass = $row["password"];
// ヒアドキュメントで表示
// <<< EOS から EOS までをhtml形式で表示
// 中で 変数も展開される
echo <<<EOS
<dl>
<dd>$id</dd>
<dd>$user</dd>
<dd>$pass</dd>
</dl>
EOS;
} -
fetch(PDO::FETCH_ASSOC)
↑ mysql_fetch_assoc と同義
EOSは勝手に付けています。なんでも良いので。 - メジャーなのはEOF…
End Of File
ファイルは違和感全開なので、
End Of Strings
文字列ってことにしてみました。 - EOS;の前にはスペースやタグは入れないこと!
- 6: delete文
- データ削除は簡単。
-
// "test2"のデータを削除
$sql = $pdo -> query("DELETE FROM users WHERE user_name='test2';");
$sql->execute(); - $sqlでsql文を作成して、execute();で実行するだけ。
- 7: drop文
- データではなく、入れ物自体の削除。
これも簡単。 -
// tableの削除
$sql = $pdo -> query("DROP TABLE IF EXISTS users,texts;");
$sql->execute(); -
// databaseの削除
$sql = $pdo -> query("DROP DATABASE IF EXISTS bbs;");
$sql->execute();
- 8: 総括
-
[宣言]
これから作成するものに関しては、すべてPDOを使用します。
理由は3点。
1: 非推奨となっている。
2: MySQL以外の他データベースでも使用可。
3: ヒアドキュメントが便利
逆にPDOを使わないと、これからはダメなのでしょう。
ヒアドキュメントはsprintfよりも視認性が高いので利用していこうと思う。
私の好きなコードを揃えるのも簡単。
(PHP_EOLを使用しなくても改行される。)
データベースは、やることが決まっていて基本はCRUDだけ。
難しいのは…
必要なカラムや他とbindしたりの初期設定や明確な構造をいかに作成するか。
今後の課題でもありますね。
でも基本はsql文というのも分かったし、
一度使えるようになったら、違うデータベースでもPDOでアクセス出来るからマスターしたいな。。。
本気でやり出したら、面白いかも。