採点されません。匿名です。 間違えることは学習の一部です。読むだけでもかまいません。

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 一覧 (横並び比較)

DBDSN 例
SQLitesqlite:/path/to/file.sqlite
MySQLmysql:host=localhost;dbname=mydb;charset=utf8mb4
PostgreSQLpgsql: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 扱い)、次の順で標準出力に表示する。

  1. 採用ドライバ名
  2. SQLite の DSN サンプル文字列
  3. MySQL の DSN サンプル文字列
  4. PostgreSQL の DSN サンプル文字列
  5. 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 pingfetchColumn() で取得
  • mysql / pgsql の後ろのスペースは 2 つ。出力フォーマットを揃えるため

なぜ DSN サンプルを直接書くのか

MySQL / PostgreSQL は今回の採点環境では起動していないので、実接続はせず DSN 文字列を出力するだけ にしている。実際にコンテナを立てて接続したい場合は、リポジトリ直下の docker/README.md を参照。