ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
PHP で DB に接続する方法の全体像
PHP には大きく分けて 3 つの DB 接続 API があります。
| API | 対応 DB | 状態 | 推奨度 |
|---|---|---|---|
| PDO | MySQL/PostgreSQL/SQLite/SQL Server/Oracle 他 | 標準・継続開発中 | ★★★ 新規開発の第一選択 |
| mysqli | MySQL / MariaDB のみ | 標準・継続 | ★★ MySQL 固有機能を使う場合 |
| MySQL のみ | PHP 7.0 で削除済 | 使用禁止 |
PDO で MySQL に接続
<?php
$dsn = 'mysql:host=127.0.0.1;port=3306;dbname=app;charset=utf8mb4';
$user = 'app_user';
$pass = 'secret';
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // 例外で受ける
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // 連想配列で返す
PDO::ATTR_EMULATE_PREPARES => false, // ネイティブ prepare
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci",
];
try {
$pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
error_log('DB connect failed: ' . $e->getMessage());
http_response_code(500);
exit('DB error');
}
各オプションの意味
- ATTR_ERRMODE = ERRMODE_EXCEPTION: エラー時に
PDOExceptionをスロー。これを設定しないとサイレントに失敗する - ATTR_DEFAULT_FETCH_MODE = FETCH_ASSOC:
fetch()がカラム名キーの連想配列を返す - ATTR_EMULATE_PREPARES = false: PHP 側エミュレーションを切ってサーバ側 prepare を使う。プレースホルダが整数として扱われる等、型情報が正確になる
- MYSQL_ATTR_INIT_COMMAND: 接続直後に実行する SQL。文字コード固定に使う
プリペアドステートメント (SQL インジェクション対策)
// ❌ NG: 直接埋め込み (SQL インジェクション脆弱)
$email = $_POST['email'];
$pdo->query("SELECT * FROM users WHERE email = '$email'");
// ✅ 名前付きプレースホルダ
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email AND status = :status');
$stmt->execute([
':email' => $_POST['email'],
':status' => 'active',
]);
$user = $stmt->fetch();
// ✅ ? プレースホルダ (順序依存)
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = ? AND status = ?');
$stmt->execute([$_POST['email'], 'active']);
$user = $stmt->fetch();
// 複数件取得
$stmt = $pdo->prepare('SELECT id, name FROM users WHERE created_at > ?');
$stmt->execute(['2025-01-01']);
foreach ($stmt as $row) {
echo $row['id'] . ': ' . $row['name'] . PHP_EOL;
}
// INSERT で採番された ID を取得
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (?, ?)');
$stmt->execute(['Tanaka', 'tanaka@example.com']);
$newId = $pdo->lastInsertId();
トランザクション
try {
$pdo->beginTransaction();
$pdo->prepare('UPDATE accounts SET balance = balance - ? WHERE id = ?')
->execute([1000, 1]);
$pdo->prepare('UPDATE accounts SET balance = balance + ? WHERE id = ?')
->execute([1000, 2]);
$pdo->commit();
} catch (Throwable $e) {
$pdo->rollBack();
throw $e;
}
// ネストしたトランザクション (SAVEPOINT)
$pdo->beginTransaction();
try {
$pdo->exec('UPDATE foo SET x = 1');
$pdo->exec('SAVEPOINT sp1');
try {
$pdo->exec('UPDATE bar SET y = 2');
} catch (PDOException $e) {
$pdo->exec('ROLLBACK TO SAVEPOINT sp1');
}
$pdo->commit();
} catch (Throwable $e) {
$pdo->rollBack();
}
mysqli で接続する場合
<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$mysqli = new mysqli('127.0.0.1', 'app_user', 'secret', 'app', 3306);
$mysqli->set_charset('utf8mb4');
} catch (mysqli_sql_exception $e) {
error_log($e->getMessage());
exit('DB error');
}
// プリペアドステートメント
$stmt = $mysqli->prepare('SELECT id, name FROM users WHERE email = ?');
$stmt->bind_param('s', $_POST['email']); // s=string, i=int, d=double, b=blob
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
echo $row['id'] . ': ' . $row['name'] . PHP_EOL;
}
// オブジェクト指向 と 手続き型の使い分け
$mysqli->close();
他 DB への接続 (PDO で統一)
// PostgreSQL
$pdo = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=app', 'postgres', 'secret');
// SQLite
$pdo = new PDO('sqlite:/var/db/app.sqlite');
$pdo = new PDO('sqlite::memory:'); // メモリ DB
// SQL Server
$pdo = new PDO('sqlsrv:Server=localhost;Database=app', 'sa', 'secret');
// または ODBC 経由
$pdo = new PDO('odbc:Driver={ODBC Driver 18 for SQL Server};Server=localhost;Database=app', 'sa', 'secret');
// Oracle
$pdo = new PDO('oci:dbname=//localhost:1521/XEPDB1', 'app', 'secret');
Laravel での DB 接続 (内部は PDO)
// .env
// DB_CONNECTION=mysql
// DB_HOST=127.0.0.1
// DB_PORT=3306
// DB_DATABASE=app
// DB_USERNAME=app_user
// DB_PASSWORD=secret
use Illuminate\Support\Facades\DB;
// DB Facade (クエリビルダ)
$users = DB::table('users')->where('status', 'active')->get();
// 生 SQL
$users = DB::select('SELECT * FROM users WHERE email = ?', [$email]);
// Eloquent モデル
$user = User::where('email', $email)->first();
// 内部の PDO インスタンス取得 (低レベル操作)
$pdo = DB::connection()->getPdo();
接続プールについて
PHP はリクエストごとにプロセスが終了するモデルなので、Java や Node.js のような長寿命接続プールが直接は使えません。
| 方式 | 解説 | 注意 |
|---|---|---|
| PDO::ATTR_PERSISTENT | PHP-FPM ワーカ単位で接続を再利用 | セッション変数が残る・MySQL 側の接続数が増えがち |
| ProxySQL | PHP と MySQL の間に挟む TCP プロキシ | 本番運用での定番。クエリルーティングも可 |
| RDS Proxy | AWS のマネージドプール | Lambda / ECS Fargate で必須に近い |
| PgBouncer | PostgreSQL 用のプール | セッションプール / トランザクションプール / ステートメントプール |
セキュリティのベストプラクティス
- 接続情報は環境変数 (.env) で管理、リポジトリに含めない
- アプリケーション用ユーザは最小権限に絞る (DROP / GRANT は不要)
- 本番は TLS 接続を強制 (
PDO::MYSQL_ATTR_SSL_CA) - SQL は必ずプリペアドステートメント、文字列結合は禁止
- エラーメッセージをそのまま画面に出さない (情報漏洩)
FAQ
Q: PDO と mysqli、どちらを使うべき?
A: 新規開発は PDO。複数 DB 対応・抽象度が高い・標準的な記法が確立されている。MySQL 限定で get_result() 等の機能が必要なら mysqli。
Q: 接続が遅い
A: localhost 指定が UNIX ソケット経由になる。明示的に 127.0.0.1 を指定すると TCP 経由、その逆も。DNS 解決遅延の場合は IP 直書きで改善。
Q: 「too many connections」エラー
A: MySQL の max_connections 不足。一時的にはサーバ側で増やせるが、根本的にはコネクションプーラ (ProxySQL) の導入を検討。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?