MySQL

PHPからMySQLを使う

PDOで接続し、入力値を安全にSQLへ渡します。

MySQL入門の講座一覧

01

PDOで接続する

PDOはPHPからデータベースへ接続するための標準的な仕組みです。接続情報は環境変数や設定ファイルで管理し、公開リポジトリへパスワードを置きません。

db.phpPHP
<?php
$dsn = 'mysql:host=127.0.0.1;dbname=study_mysql;charset=utf8mb4';
$pdo = new PDO($dsn, $_ENV['DB_USER'], $_ENV['DB_PASSWORD'], [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

接続に失敗したときは、ホスト、ポート、DB名、ユーザー、パスワード、PDO MySQLドライバーの有無を順に確認します。

02

プレースホルダーで検索する

products.phpPHP
<?php
require __DIR__ . '/db.php';

$minPrice = 500;
$stmt = $pdo->prepare(
    'SELECT name, price FROM products
     WHERE price >= :min_price
     ORDER BY price DESC'
);
$stmt->execute(['min_price' => $minPrice]);

foreach ($stmt as $product) {
    echo htmlspecialchars($product['name'], ENT_QUOTES, 'UTF-8');
    echo ': ' . $product['price'] . '円<br>';
}
ブラウザーの表示例OUTPUT
MySQL入門書: 2800.00円
マグカップ: 900.00円

DECIMAL(10, 2)の値は、この例のPDO設定では文字列"2800.00"のように取得されます。整数表示にしたい場合は、表示側で明示的に書式を指定します。SQLへ値を文字列連結しないことがSQLインジェクション対策の基本です。HTMLへ出力するときは、SQLとは別にHTMLエスケープも行います。

03

フォームの値を追加する

入力値を検証して追加するPHP
$name = trim($_POST['name'] ?? '');
$price = filter_input(INPUT_POST, 'price', FILTER_VALIDATE_FLOAT);

if ($name === '' || $price === false || $price < 0) {
    throw new InvalidArgumentException('商品名と価格を確認してください。');
}

$stmt = $pdo->prepare(
    'INSERT INTO products (name, price, stock)
     VALUES (:name, :price, :stock)'
);
$stmt->execute([
    'name' => $name,
    'price' => $price,
    'stock' => 0,
]);
入力が不正な場合の表示例OUTPUT
商品名と価格を確認してください。

入力検証は利用者向けのエラー表示、プレースホルダーはSQLの安全性、出力エスケープはHTMLの安全性を守ります。役割を混ぜないようにします。

04

PHPからトランザクションを使う

注文と在庫を一緒に更新するPHP
try {
    $pdo->beginTransaction();

    $stmt = $pdo->prepare(
        'UPDATE products
         SET stock = stock - :quantity
         WHERE id = :id AND stock >= :quantity'
    );
    $stmt->execute(['quantity' => 1, 'id' => 1]);

    if ($stmt->rowCount() !== 1) {
        throw new RuntimeException('在庫がありません。');
    }

    $stmt = $pdo->prepare(
        'INSERT INTO orders (product_id, quantity, ordered_at)
         VALUES (:product_id, :quantity, CURRENT_DATE)'
    );
    $stmt->execute(['product_id' => 1, 'quantity' => 1]);
    $pdo->commit();
} catch (Throwable $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    throw $e;
}

どちらかのSQLが失敗したら、在庫だけ減る状態を残さず、全体を取り消します。利用者へ見せるメッセージと、ログへ記録する詳細な例外を分けることも大切です。

05

安全に運用する

  • DBユーザーへ必要最小限の権限だけを与える
  • 接続情報を環境変数や秘密管理へ分ける
  • エラーメッセージへSQLやパスワードを表示しない
  • 入力検証、プレースホルダー、出力エスケープを別々に行う
  • テスト用と本番用のデータベースを分ける

PHPの書き方だけで安全性が決まるわけではありません。MySQLの権限、サーバーのネットワーク、バックアップと復元まで含めて確認します。