PHPのフォームからデータベースにデータを追加してみよう

フォルダとファイル名

php-db フォルダに db06.php を作成します。
このページでは、INSERT INTO 構文を使ってフォームから、データベースに新しいユーザーを追加します。

基本コード(db06.php)

  1. すでに登録されているユーザー一覧を表示(SELECT)
  2. フォームから名前とメールをPOST送信(INSERT)
  3. 登録に成功したら、一覧にすぐ反映
<?php
$dsn = 'mysql:host=localhost;dbname=testdb;charset=utf8mb4';
$user = 'root';
$password = '';

// エスケープ関数
function h($str)
{
    return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}

try {
    $pdo = new PDO($dsn, $user, $password);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $msg = '';
    $errors = [];

    // 1) フォーム送信があった場合
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $name = trim($_POST['name'] ?? '');
        $email = trim($_POST['email'] ?? '');

        if ($name === '') {
            $errors[] = '名前が入力されていません。';
        }
        if ($email === '') {
            $errors[] = 'メールが入力されていません';
        } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $errors[] = 'メールの入力形式が異なります';
        }

        if (count($errors) === 0) {
            $stmt = $pdo->prepare("INSERT INTO users (name, email, created_at) VALUES (?, ?, NOW())");
            $stmt->execute([$name, $email]);
            $msg = "新しいユーザーを追加しました。";
        }
    }

    $stmt = $pdo->query("SELECT * FROM users ORDER BY id ASC");
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
    echo "エラー:" . $e->getMessage();
    exit;
}
?>
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>ユーザー一覧(追加機能付き)</title>
    <style>
        table {
            border-collapse: collapse;
            margin-bottom: 1em;
        }

        th,
        td {
            border: 1px solid #666;
            padding: .5em 1em;
        }

        form {
            margin-top: 2em;
        }
    </style>
</head>

<body>
    <h1>ユーザー一覧</h1>
    <?php if ($errors): ?>
        <ul class="error">
            <?php foreach ($errors as $error): ?>
                <li><?= h($error) ?></li>
            <?php endforeach ?>
        </ul>
    <?php endif; ?>


    <?php if ($msg): ?>
        <p class="success"><?= h($msg) ?></p>
    <?php endif; ?>


    <table>
        <tr>
            <th>ID</th>
            <th>名前</th>
            <th>メール</th>
            <th>登録日時</th>
        </tr>
        <?php foreach ($rows as $row): ?>
            <tr>
                <td><?= h($row['id']) ?></td>
                <td><?= h($row['name']) ?></td>
                <td><?= h($row['email']) ?></td>
                <td><?= h($row['created_at']) ?></td>
            </tr>
        <?php endforeach; ?>
    </table>

    <h2>新しいユーザーを追加</h2>
    <form method="post">
        <label>名前:
            <input type="text" name="name" required>
        </label><br>
        <label>メール:
            <input type="email" name="email" required>
        </label><br>
        <button type="submit">追加する</button>
    </form>
</body>

</html>

フォーム送信されたらINSERT処理

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name = trim($_POST['name'] ?? '');
    $email = trim($_POST['email'] ?? '');
  • $_POST['name']$_POST['email'] でフォームの入力値を受け取ります。
  • trim() を使って、前後の空白を除去します。

バリデーション

フォームから送信されたメールアドレスが正しい形式かどうかをチェックするには、
PHP には filter_var() という便利な関数があります。

if ($name === '') {
            $errors[] = '名前が入力されていません。';
        }
        if ($email === '') {
            $errors[] = 'メールが入力されていません';
        } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            $errors[] = 'メールの入力形式が異なります';
        }

filter_var() とは?

filter_var() は PHP に標準で用意されている 入力データの検証(バリデーション)や整形(サニタイズ) を行う関数です。

filter_var(調べたい値, フィルタの種類);

メールアドレスをチェックする

メールアドレスの場合は、FILTER_VALIDATE_EMAIL という定数を使います。

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    $errors[] = 'メールの入力形式が異なります';
}
  • 正しいメール形式(xxx@yyy.zz) のとき → 値をそのまま返す
  • 正しくないメール形式 のとき → false を返す

つまり、「正しい形式じゃなければエラー」と判断できます。

preg_match との違い

  • preg_match → 自分で正規表現パターンを書く必要がある
    (難しい・見づらい・間違いやすい)
  • filter_var → PHP が用意してくれたルールで判定してくれる
    (読みやすい・メンテナンスしやすい)

バリデーション系(値が正しいかチェックする)

定数用途
FILTER_VALIDATE_EMAILメールアドレスかどうかuser@example.com
FILTER_VALIDATE_URLURLかどうかhttps://example.com
FILTER_VALIDATE_INT整数かどうか123 , 12.3
FILTER_VALIDATE_FLOAT小数を含む数値かどうか12.3

サニタイズ系(危険な文字を除去する)

定数用途
FILTER_SANITIZE_STRINGHTMLタグを除去(※PHP 8.1で非推奨)<b>abc</b>abc
FILTER_SANITIZE_EMAILメールアドレスに使えない文字を除去test@ex ample.comtest@example.com
FILTER_SANITIZE_URLURLに使えない文字を除去https://exa mple.comhttps://example.com
FILTER_SANITIZE_NUMBER_INT数字と符号だけ残す+123abc+123

詳しくはマニュアルサイトを参照 https://www.php.net/manual/ja/function.filter-var.php

エラーの配列が空だったら、INSERT INTO

        if (count($errors) === 0) {
            $stmt = $pdo->prepare("INSERT INTO users (name, email, created_at) VALUES (?, ?, NOW())");
            $stmt->execute([$name, $email]);
            $msg = "新しいユーザーを追加しました。";
        }
  • NOW() は現在の日時(タイムスタンプ)を自動で入れてくれます。
  • プレースホルダー ? を使うことで SQL インジェクションを防止できます。

一覧を表示(SELECT)

$stmt = $pdo->query("SELECT * FROM users ORDER BY id ASC");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
  • 常に users テーブルの全レコードを取得して、テーブルに表示します。
  • 新しいユーザーが追加されるたびに、この一覧にも表示されます。