SQLクエリを実行する関数について、
複数あるので、その違いをまとめてみた。
○exec
http://php.net/manual/ja/pdo.exec.php
一度の関数コールで SQL 文を実行し、
文によって作用した行数を返す。
“insert”、”delete”など、
SQL 文の実行で完結する場合に使える。
○query
http://php.net/manual/ja/pdo.query.php
SQL ステートメントを実行し、
結果セットを PDOStatement オブジェクトとして返す。
“select”などで、返ってきたデータを活用する場合には、
“exec”は使えないので、こっちを使う。
●PDOStatement:http://php.net/manual/ja/class.pdostatement.php
○execute
http://php.net/manual/ja/pdostatement.execute.php
プリペアドステートメントを実行する。
クエリ文中の要素をパラメータにして代入したりできるので、
クエリを動的に実行したい時などに向いている。
これらを使って、プログラムを作ってみる。
準備
○テスト用のデータベース・ユーザーの作成
mysql> create database test; mysql> create table test (id int primary key auto_increment, name varchar(10)); mysql> create user testuser@localhost -> identified by 'password'; mysql> grant all on test.* to testuser@localhost;
○includeする関数の準備
データベース接続用、エスケープ用の関数は
独習PHPのサンプルソースをそのまま借用。
・DbManager.php(DB接続パラメータだけは変更)
<?php function getDb() { $dsn = 'mysql:dbname=test; host=127.0.0.1; charset=utf8'; $usr = 'testuser'; $passwd = 'password'; $db = new PDO($dsn, $usr, $passwd); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //$db = new PDO($dsn, $usr, $passwd, [PDO::ATTR_PERSISTENT => true); return $db; }
・Encode.php
<?php function e(string $str, string $charset = 'UTF-8'): string { return htmlspecialchars($str, ENT_QUOTES | ENT_HTML5, $charset); }
作成
○データを挿入し、結果を表示するプログラム。
・insert.php
<?php require_once 'DbManager.php'; require_once 'Encode.php'; $query1 = "INSERT INTO test (name) VALUES ('test1')"; $query2 = "SELECT * from test"; try { $db = getDb(); $stt1 = $db->exec($query1); $stt2 = $db->query($query2); ?> <!DOCTYPE html> <html> <head><title>PHP TEST INSERT</title></head> <body> <h3>データを挿入しました</h3> <table border=1> <th>id</th><th>名前</th> <?php while($row = $stt2->fetch(PDO::FETCH_ASSOC)){ ?> <tr> <td><?=e($row['id'])?></td> <td><?=e($row['name'])?></td> </tr> <?php } ?> </table> </body> </html> <?php } catch(PDOException $e) { print "エラーメッセージ:{$e->getMessage()}"; } finally { $db = null; }
○実行結果
F5を押すと行数が増えてくっていう、
シュールなプログラムになりましたw
でも実際は、挿入するデータも、
フォームから受け取ったデータだったりするので、
executeを使う方が現実的。
・insert2.php
<?php require_once 'DbManager.php'; require_once 'Encode.php'; $name = 'test1'; // $name = e($_POST['name']); $query1 = "INSERT INTO test (name) VALUES (:name)"; $query2 = "SELECT * from test where id=:id"; try { $db = getDb(); $stt1 = $db->prepare($query1); $stt1->bindValue(':name', $name); $stt1->execute(); $insert_id = $db->lastInsertId(); $stt2 = $db->prepare($query2); $stt2->bindValue(':id', $insert_id); $stt2->execute(); $row = $stt2->fetch(PDO::FETCH_ASSOC); } catch(PDOException $e) { print "エラーメッセージ:{$e->getMessage()}"; } finally { $db = null; } ?> <!DOCTYPE html> <html> <head><title>PHP TEST INSERT</title></head> <body> <h3>データを挿入しました</h3> 挿入したデータは以下の通りです。 <table border=1> <th>id</th><th>名前</th> <tr> <td><?=e($row['id'])?></td> <td><?=e($row['name'])?></td> </tr> </table> </body> </html>
○実行結果
多分、こっちの場合の方が多いですね。
結果の表示も、挿入したデータだけにできました。
(クエリ文を’.’でつなげたりして作るのは好ましくなく、
動的なクエリ文の場合は、プレイスホルダで記述すべきとのこと)
また、削除とかの場合は、
削除するデータを指定してあげることがほとんどだと思うので、
このやり方を使う方が多いでしょう。
・delete.php
<?php require_once 'DbManager.php'; require_once 'Encode.php'; $query1 = 'SELECT * from test where id=:id'; $query2 = 'DELETE from test where id=:id'; $id = 1; // $id = e($_POST['id']); try { $db = getDb(); $stt1 = $db->prepare($query1); $stt1->bindValue(':id', $id); $stt1->execute(); $row = $stt1->fetch(PDO::FETCH_ASSOC); $stt2 = $db->prepare($query2); $stt2->bindValue(':id', $id); $stt2->execute(); } catch(PDOException $e) { print "エラーメッセージ:{$e->getMessage()}"; } finally { $db = null; } ?> <!DOCTYPE html> <html> <head><title>PHP TEST DELETE</title></head> <body> <h3>データを削除しました</h3> 削除したデータは以下の通りです。 <table border=1> <th>id</th><th>名前</th> <tr> <td><?=e($row['id'])?></td> <td><?=e($row['name'])?></td> </tr> </table> </body> </html>
○実行結果
そんな感じで、insert,select,update,deleteでは、
prepare->executeを使う場合が多いんですかね?
ただ、必要ない場合は、exec等を使った方が、
ソースが短くてスッキリするのかなと・・・