PHPでMySQLに接続する設定は最近のフレームワークでは隠蔽されていて特に考えなくても大丈夫になっていますが、生のPHPではどう言う風に設定するかをまとめてみました。
接続する処理
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// パラメーター const DB_HOST = "127.0.0.1"; const DB_NAME = "sample_products"; const DB_PORT = "8889"; const DB_USER = "root"; const DB_PASS = "root"; ini_set('log_errors', 'on'); ini_set('error_log', 'test.log'); $options = [ // 接続した後に実行されるコマンド PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET 'utf8'", // エラー時の処理 -> 例外をスロー PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // データのフェッチした後のスタイル -> カラム名をキーとする連想配列 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; try { $pdo = new PDO( "mysql:dbname=".DB_NAME."; host=".DB_HOST."; port=".DB_PORT."; charset=utf8", DB_USER, DB_PASS, $options ); } catch (Exception $e) { error_log($e); } |
説明
接続のパラメーター
DBにアクセスするのに必要な情報は以下の通り
- ホスト名: DBが建っているサーバのIP
- ポート名: サーバでDBを建てているポート番号
- データベース名: アクセスするスキーマ情報
- ユーザ名: アクセスするユーザ情報
- パスワード: 上記のユーザ名で上記のデータベース名にアクセスするために必要なパスワード
これらを定数として定義しておく
1 2 3 4 5 |
const DB_HOST = "127.0.0.1"; const DB_NAME = "sample_products"; const DB_PORT = "8889"; const DB_USER = "root"; const DB_PASS = "root"; |
接続際のオプション
デフォルトではエラー時に例外を出さなかったり、取得したデータが少々扱いずらかったりするので、その手間を省く設定を行う
自分がよく行う設定は以下の通り
- PDO::MYSQL_ATTR_INIT_COMMAND(接続時に実行されるコマンド) => "SET CHARACTER SET 'utf8'" (文字コードをutf8にする)
- PDO::ATTR_ERRMODE(エラー時の処理) => PDO::ERRMODE_EXCEPTION(例外を出す)
- PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC(カラム名をキーとする連想配列)
これを以下のように定義
1 2 3 4 5 6 7 8 |
$options = [ // 接続した後に実行されるコマンド PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET 'utf8'", // エラー時の処理 -> 例外をスロー PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // データのフェッチした後のスタイル -> カラム名をキーとする連想配列 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; |
PDO(php database object)でデータベース接続を行う
phpではPDO(php dabase object)と言うクラスがあり、これに上記のパラメータを渡してインスタンスを作ると自動でDBに接続したインスタンスが返ってくる。
でも、接続に成功するかどうかはDBのサーバの状態(もしかしたら、落ちているかもしれないので)例外処理も書いた方が良い
1 2 3 4 5 6 7 8 9 10 |
try { $pdo = new PDO( "mysql:dbname=".DB_NAME."; host=".DB_HOST."; port=".DB_PORT."; charset=utf8", DB_USER, DB_PASS, $options ); } catch (Exception $e) { error_log($e); } |
クエリを実行する処理
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
try { // sqlクエリ情報をセット $stmt = $pdo->prepare("SELECT * FROM products"); // クエリを実行 $stmt->execute(); // パラメータを設定する場合 $stmt = $pod->prepare("SELECT * FROM members WHERE name => :name"); $data = [ ":name" => "taro" ]; $stmt->execute($data); } catch (Exception $e) { error_log($e); } |
説明
クエリを設定する
PDOオブジェクトにはprepareと言う実行するクエリの情報を返すメソッドがある
これを使って、SQL文をセットする
1 2 |
// sqlクエリ情報をセット $stmt = $pdo->prepare("SELECT * FROM products"); |
クエリを実行する
実行した文情報はPDOStatementクラスのインスタンスを返す。
このクラスにはexecuteと言うセットされたSQL文を実行するメソッドがある。
これを使って、SQL文を実行する。
1 2 |
// クエリを実行 $stmt->execute(); |
また、WHERE区などでパラメータを指定したい場合は以下のようにする
1 2 3 4 5 6 |
// パラメータを設定する場合 $stmt = $pod->prepare("SELECT * FROM members WHERE name => :name"); $data = [ ":name" => "taro" ]; $stmt->execute($data); |
クエリの結果を取得する処理
サンプルコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
try { // これはさっきのSQL実行の処理 $stmt = $pdo->prepare("SELECT * FROM products"); $stmt->execute(); // データを一軒ずつ取得 while ($row = $stmt->fetch()) { $products[] = [ 'id' => $row['id'], 'name' => $row['name'], 'price' => $row['price'], 'image' => $row['image'], 'delv' => $row['delv'], 'isSale' => $row['is_sale'] ]; } // データをまとめて取得 $products2 = $stmt->fetchAll(); } catch (Exception $e) { error_log($e); } |
説明
PDOStatementオブジェクトのfetchとfetchAll
PDOStatementオブジェクトにはfetchとfetchAllと言うどちらも取得した結果を返すメソッドがある。
取得した結果は上記のPDOインスタンスを立ち上げる際のオプションで指定した通りにカラム名を指定した連想配列になっている。
fetchは取得したデータを一軒ずつ取得する、実行する度に次のデータが返却される
fetchAllメソッドはデータをまとめて返却する。
取得したデータをそのまま配列に格納したい場合はfetchAllを使い、取得したデータを解釈し、独自の処理を加えたい場合はfetchで一件ずつ取得するのが望ましい。
まとめ
DBからデータを取ってくるたけでも、
- PDOインスタンスを作る
- SQL文をセットしてPDOStatementインスタンスを作る
- SQL文を実行する
- 実行した結果を取得する
の流れを覚えておく必要があり、意外と大変だと感じるだろう。
最近のフレームワークではこうしたことを考えずにデータを直感的に取得できるようになっている。(それが良いことかどうかは分からないけど)
最後に全体のソースを載せて締めにしよう
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
const DB_HOST = "127.0.0.1"; const DB_NAME = "sample_products"; const DB_PORT = "8889"; const DB_USER = "root"; const DB_PASS = "root"; ini_set('log_errors', 'on'); ini_set('error_log', 'test.log'); $options = [ // 接続した後に実行されるコマンド PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET 'utf8'", // エラー時の処理 -> 例外をスロー PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // データのフェッチした後のスタイル -> カラム名をキーとする連想配列 PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]; try { $pdo = new PDO( "mysql:dbname=".DB_NAME."; host=".DB_HOST."; port=".DB_PORT."; charset=utf8", DB_USER, DB_PASS, $options ); } catch (Exception $e) { error_log($e); } $products = []; try { $stmt = $pdo->prepare("SELECT * FROM products"); $stmt->execute(); while ($row = $stmt->fetch()) { $products[] = [ 'id' => $row['id'], 'name' => $row['name'], 'price' => $row['price'], 'image' => $row['image'], 'delv' => $row['delv'], 'isSale' => $row['is_sale'] ]; } } catch (Exception $e) { error_log($e); } |