DSN 比較 / 複数 DB 接続
テクノロジ系 / db (PDO / SQL / マルチDB)
DSN 比較 / 複数 DB 接続
Lesson 11 / Chapter 10
PDO は「DSN だけ」で接続先を切り替えられる
<?php $pdo = new PDO($dsn, $user, $pass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
- DSN (Data Source Name) = どの DB のどこに繋ぐかを表す文字列
- DSN 以外の SQL コード (SELECT / INSERT / prepare / fetch) は 3 DB で同じ
- → 「アプリは PHP のまま、DB だけ差し替える」が成立する
SQLite の DSN
<?php $dsn = "sqlite:/path/to/file.sqlite"; $pdo = new PDO($dsn);
- ファイルパスを直接書くだけ
- ユーザ / パスワード不要 (ローカルファイル)
- 学習や軽い実験に向いている
MySQL の DSN
<?php $dsn = "mysql:host=localhost;dbname=mydb;charset=utf8mb4"; $pdo = new PDO($dsn, "root", "secret");
host/dbname/charsetを;で並べる- ユーザ・パスワードは PDO の 2,3 番目の引数
charset=utf8mb4を必ず付ける (絵文字含む UTF-8 のため)
PostgreSQL の DSN
<?php $dsn = "pgsql:host=localhost;dbname=mydb"; $pdo = new PDO($dsn, "postgres", "secret");
- 書式は MySQL と似ているが先頭が
pgsql: - charset は SQL レイヤで決まる (DSN で指定しない)
- ポート指定が必要なら
;port=5432を追加
DSN 一覧 (横並び比較)
| DB | DSN 例 |
|---|---|
| SQLite | sqlite:/path/to/file.sqlite |
| MySQL | mysql:host=localhost;dbname=mydb;charset=utf8mb4 |
| PostgreSQL | pgsql:host=localhost;dbname=mydb |
- 共通:
ドライバ名:で始まる - 共通:
;区切りで key=value - 違い: ファイルパス vs ホスト+DB 名
環境変数で切り替える
<?php
$driver = getenv('DOJO_DB_DRIVER') ?: 'sqlite';
$dsn = match ($driver) {
'sqlite' => "sqlite:" . getenv('DOJO_DB_PATH'),
'mysql' => "mysql:host=localhost;dbname=mydb;charset=utf8mb4",
'pgsql' => "pgsql:host=localhost;dbname=mydb",
};
$pdo = new PDO($dsn);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);→ コードはこのままで、DOJO_DB_DRIVER=mysql にすれば MySQL に繋がる。
このチャプターでできるようになること
✅ SQLite / MySQL / PostgreSQL の DSN 書式を読み分けられる
✅ PDO は DSN を差し替えるだけで複数 DB に対応できると説明できる
✅ 環境変数で接続先を切り替える発想が持てる
✅ mysql: には charset=utf8mb4 を付ける習慣
→ ドリルへ (実接続は SQLite で行い、MySQL/PostgreSQL は DSN サンプル出力で確認)
考えてみよう
既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。
ドリル 01 — DSN を 3 種類並べて、SQLite に実接続する
問題
環境変数 DOJO_DB_DRIVER を読み取り (未設定なら sqlite 扱い)、次の順で標準出力に表示する。
- 採用ドライバ名
- SQLite の DSN サンプル文字列
- MySQL の DSN サンプル文字列
- PostgreSQL の DSN サンプル文字列
- SQLite (
DOJO_DB_PATH) に実接続し、pingテーブルの行数を出力
期待される出力
driver: sqlite sqlite DSN sample: sqlite:/path/to/file.sqlite mysql DSN sample: mysql:host=localhost;dbname=mydb;charset=utf8mb4 pgsql DSN sample: pgsql:host=localhost;dbname=mydb connected: yes (rows=1)
採点
php scripts/grade.php topics/db/ch10-multi-db/drill/01-dsn-comparison/
採点ランナーは tests/setup.sql を一時 SQLite に流し込み、DOJO_DB_PATH を渡してきます。DOJO_DB_DRIVER は未指定なので、デフォルトの sqlite で動かす想定です。
ヒント
getenv('DOJO_DB_DRIVER') ?: 'sqlite'でデフォルト値- DSN サンプルは 固定文字列を直接 echo する (実環境のパスではなく
/path/to/file.sqliteで OK) - SQLite への実接続は
new PDO('sqlite:' . getenv('DOJO_DB_PATH')) - 行数は
SELECT COUNT(*) FROM pingをfetchColumn()で取得 mysql/pgsqlの後ろのスペースは 2 つ。出力フォーマットを揃えるため
なぜ DSN サンプルを直接書くのか
MySQL / PostgreSQL は今回の採点環境では起動していないので、実接続はせず DSN 文字列を出力するだけ にしている。実際にコンテナを立てて接続したい場合は、リポジトリ直下の docker/README.md を参照。