LABO IWASAKI

PDOでMySQLに接続してINSERTやUPDATEやSELECTやSUM

PDOで色々やる

今でこそ普通に使ってるPDOですが…
もぅ使い始めの頃は難しくて困っていました。
まずPDOってモノが一体何なのか、からだった。

よく「PHPマニュアル見ろ」と聞きますが
申し訳ないけど、あれは読んでも分からんのだ。
同じように感じた人の為に残しておきます。

PDOってなんだ

What is PDO

PDOとは…
「PHP Data Objects」の頭文字をとった名称です。

データアクセス抽象化レイヤーと言われ、アプリケーションとDBMS(データベース管理システム)の間に入ってDBMSの違いを意識せずにアプリケーションを作成するものです。

つまりですね、データベースってMySQL以外にも色々ある訳ですが、そのデータベースの違いを意識しないで同じ書き方で使えるって事ですね。データベースによって若干の差異はあるそうですが…。

PDOとは、そのデータアクセス抽象化レイヤの一つで、PHP5.1からバンドル(標準で使えるようになってる)されてます。

僕はそんな経験ないけど、プロジェクトが途中でデータベースの種類を変更しなければならない時とかにも対応できるから便利らしい。

セキュリティ的にもSQLインジェクションの心配がなかったり(後述)してイイです。

前置きはこのくらいにしておきます。

PDOでDBに接続

Connect MySQL

try {
$pdo = new PDO('mysql:host=ホスト名;dbname=DB名;charset=utf8','ユーザー名','パスワード',
array(PDO::ATTR_EMULATE_PREPARES => false));
} catch (PDOException $e) {
 exit('データベース接続失敗。'.$e->getMessage());
}
try {
$pdo = new PDO('mysql:host=ホスト名;dbname=DB名;charset=utf8','ユーザー名','パスワード');
} catch (PDOException $e) {
 exit('データベース接続失敗。'.$e->getMessage());
}

$pdo」は変数だから好きな文字にできます。
「try」 に接続する情報を書いて catchでエラー情報を投げてます。

3行目の「PDO::ATTR_EMULATE_PREPARES」について。
エミュレートプリペアーズって読むのかな??
EMULATEは「模倣する」とか「手本とする」みたいな意味で、主にコンピュータシステムに関して使われてるみたいです。
プリペアドステートメント(後述)は、文を用意して、値や条件をバインドして、実行する。みたいな感じなので、通信を2回するみたいで、ちょっと効率よくないらしい。
そういうのを「無駄な事せずに効率よくやるよ」っていうヤツ。
これを設定してるとSQLを正しく実行してくれるそうです。
そして、PHP5.2以降はデフォルトなので設定しなくて大丈夫になりました。

PDOでデータ取得

PDO MySQL Select

データベースのテーブル「mydata」から情報を取得します。
「mydata」には「id」「name」「age」というデータが入っている仮定です。 この時、id 1 に自分のデータが入っているとします。

$stmt = $pdo -> prepare("SELECT * FROM mydata WHERE id=:id");
$stmt -> bindValue(':id', 1, PDO::PARAM_INT);
$stmt -> execute();

if ($rows = $stmt -> fetch()) {
    $name = $rows["name"];
    $age = $rows["age"];
}
$stmt -> bindParam(':id', $myid, PDO::PARAM_STR);

「$stmt」「$rows」は変数だから好きな文字にできます。
bindValuebindParamに関しては後述します。

1行目の「prepare」について。
プリペアと読み、「用意された」とか「心構え」って意味です。
PDOでこのSQLを実行する前に、あらかじめ、そこに入れる値を用意しておく、って事ですね。
「execute」は「実行する」という意味です。
これを書かないと、ただ用意しただけで、何も起こりません。

PDOでINSERT

PDO MySQL INSERT

$stmt = $pdo -> prepare("INSERT INTO mydata (id,name,age) VALUES ('', :name, :age)");
$stmt -> bindParam(':name', $myname, PDO::PARAM_STR);
$stmt -> bindValue(':age', $myage, PDO::PARAM_STR);
$stmt -> execute();

// 1行目の VALUES('', :name, :age) で本来 id が来るところが
// 「 '' 」になっています。
// こうしておくと、DBで id がオートインクリメントの場合に最新の数字が入ります。

ここで「bindValue」と「bindParam」の説明を入れます。
変数に入っている値が違うので、注意して見てください。

      $myname = "TAKAYOSHI";
      $myage = "35";

$stmt = $pdo -> prepare("INSERT INTO mydata (id,name,age) VALUES ('', :name, :age)");
$stmt -> bindParam(':name', $myname, PDO::PARAM_STR);
$stmt -> bindValue(':age', $myage, PDO::PARAM_STR);

      $myname = "IWASAKI";
      $myage = "30";

$stmt -> execute();

bindValue」と「bindParam」ですが、bindValue は値をバインドしたら、その時点のセットした値が使われます。
つまり、上の例でいうと、「$myage」は行目の「35」が使われます。
それに対して「bindParam」はバインドの後で、セットする変数の内容が変わったら、それが使われます。
上の例で言うと行目の「$myname = "IWASAKI"」が使われるという事です。
bindParam は「評価が実行時」つまり11行目の「 execute 」の段階で入っている値が使われるのです。

bindValue と bindParam

どちらも値をバインドするのですが、bindParam は「評価が実行時」になります。
bindValue は、バインドした時点で中身が評価されます。

PDOでUPDATE

PDO MySQL UPDATE

今回は2種類の書き方を紹介します

$stmt = $pdo -> prepare("UPDATE mydata SET name =:name WHERE id = :id");
$stmt-> bindParam(':name', $myname, PDO::PARAM_STR);
$stmt-> bindValue(':id', $myid, PDO::PARAM_INT);
$stmt-> execute();
$sql = 'UPDATE mydata SET name =:name WHERE id = :id';
$stmt = $pdo -> prepare($sql);
$stmt->bindParam(':name', $myname, PDO::PARAM_STR);
$stmt->bindValue(':id', $myid, PDO::PARAM_INT);
$stmt->execute();

どちらもやっている事は同じです。
場面によって便利な方を使いましょう。

PDOでDELETE

PDO MySQL DELETE

$stmt = $pdo -> prepare("DELETE FROM mydata WHERE id = :delete_id");
$stmt -> bindValue(':delete_id', $myid, PDO::PARAM_INT);
$stmt -> execute();
$sql = "DROP TABLE IF EXISTS テーブル名";
$pdo -> exec($sql);

テーブルを削除する場合、「execute」ではなく「exec

PDOでCOUNT

PDO MySQL COUNT

そのテーブルに存在する、任意の条件にあてはまるレコード数を数える場合

$stmt = $pdo -> prepare("SELECT * FROM mydata WHERE age = :age");
$stmt -> bindValue(':age', $user_age, PDO::PARAM_INT);
$stmt -> execute();
$count = $stmt -> rowCount();

4行目でカウントしています。
他の行はSELECTの時と同じなので分かりやすいと思います。
重複していないデータの数を取得する場合はこちら ▶︎ DISTINCT

PDOでSUMする

PDO MySQL SUM

そのテーブルの特定のフィールドの合計値を計算します。
条件「Y」に当てはまる「a1」の合計を出しています。

$stmt = $pdo -> prepare("SELECT SUM(a1) as a1 FROM テーブル名 WHERE y=:y");
$stmt -> bindParam(':y', $y, PDO::PARAM_STR);
$stmt -> execute();
if($row = $stmt -> fetch()){
$total = $row['a1'];
}

ポイントは「SUM(a1) as a1」の部分です。
SUM(a1)」はa1をSUMするという事です。
as a1」は、合計した値の呼び名になります。
5行目で、変数「$total」に代入しています。
下のコードを見ると分かりやすいはずです。

$stmt = $pdo -> prepare("SELECT SUM(a1 + a2 + a3) as grandtotal FROM テーブル名 WHERE y=:y");
$stmt -> bindParam(':y', $y, PDO::PARAM_STR);
$stmt -> execute();
if($row = $stmt -> fetch()){
$total = $row['grandtotal'];
}

条件Yの時、a1 , a2 , a3を足して「grandtotal」として、それを変数「$total」に代入しています。
個人的には、このSUMをよく使います。

テーブルを作成する

CREATE TABLE

PDOを使ってテーブルを作成します。
行目の「EXISTS」は「存在するかどうか」を判定しています。
英語でexistは「存在する」とか「有る」「居る」などを指します。

$sql = "CREATE TABLE IF NOT EXISTS `テーブル名`"
."("
. "`id` INT auto_increment primary key,"
. "`name` VARCHAR(255),"
. "`y` VARCHAR(4),"
. "`m` VARCHAR(4),"
. "`d` VARCHAR(4),"
. "`week` INT,"
. "`a1` INT(11),"
. "`a2` INT,"
. "`a3` INT,"
. "`a4` INT,"
. "`MEMO` TEXT,"
. "`i_date` DATETIME"
.");";
$stmt = $pdo -> prepare($sql);
$stmt -> execute();

行目で「id」をオートインクリメントにしています。
VARCHER」は文字列(改行できない)
INT」は数値(「 01」と登録しても「 1」になる)
TEXT」は改行も可能な文字列
DATETIME」は 2015-02-11 18:30:54 のような形式の日付
()の中は保存できる桁数を指定しています。

セキュリティ

SQL INJECTION

冒頭で少し触れていますが、PDOはSQLインジェクションに対して有効(安全)だと言われています。

SQLインジェクションとは、SQL構文に意図していない命令を挿入して改変されてしまうというモノです。
INJECTION(インジェクション)」は注入する。などの意味。
PDOの場合、SQLとバインド値がDBMS(データベース管理システム)で実行されるまで、分離しているから、この攻撃を受けません。
つまり、「ここはSQL構文」ここは「バインド値」っていうふうに、ちゃんと認識してくれるから、という事です。

セキュリティに関しては、より詳しい記事を諸兄方が残してくれているので、僕は割愛します。
こちらにも寄稿しています。▶︎ PDOでMySQLに接続してinsertやupdate、sumやdelete

関連する記事

Related posts

▶︎ DISTINCTで重複していない値の数を求める
同じ値の、つまり重複したデータを取り除き、ユニークな値の数だけCOUNTする方法です。

▶ PHPでログイン機能を作成する
PHPでPDOとMySQLを用いて、パスワードをhash化したログイン機能を作ります。

▶ PHPの配列(implodeとexplodeなど)
PHPの配列(Array)に関しての色々な操作をまとめています。

▶ PHPのstrtotimeで日付の計算
strtotimeを用いて日付と曜日を求め、日付の足し引きなど計算もします。

▶ PHPでカレンダーを作る(DEMOあり)
PHPでカレンダーを作ります。DEMOもあるのでわかりやすいと思います。

▶ PHPでCSSを即時反映させる方法。
CSSがキャッシュの都合でなかなか反映されない時があります。そんな時はPHPを少し書くだけで即時反映されて便利です。