0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【PHP】フォーム送信後にチェックボックスの選択を保持する

Last updated at Posted at 2022-12-26

はじめに

実装に苦戦したので、備忘録として記事にしました。
まだまだ勉強中の身なので、知らないことがたくさんあります。
参考になると嬉しいです。

実装したいこと

問題1で「織田信長」と「ショパン」を選択し、問題2を選択せずに送信ボタンを押したとき、選択を保持したままエラーメッセージを表示する。
複数の入力画面があってエラーがでたとき、全て入力しなおすなんてことにならないように。
スクリーンショット 2022-12-26 182555.png

環境

  • XAMPP Version 8.1.10
  • Visual Studio Code Version 1.74.2

データベースの構造(phpMyadmin)

スクリーンショット 2022-12-26 181211.png

phpファイル

<?php
    //セッション開始
    session_start();
    try {
        // データベースに接続
        $pdo = new PDO(
            'mysql:dbname=xxx;host=localhost;charset=utf8',
            'xxx',
            'xxx',
            [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::ATTR_EMULATE_PREPARES =>false
            ]
        );
        //変数の定義とシリアライズ
        if(isset($_POST['question1'])){
            $question1 = $_POST['question1'];
            $question1_db = serialize($question1);
        }
        if(isset($_POST['question2'])){
            $question2 = $_POST['question2'];
            $question2_db = serialize($question2);
        }
        //form送信したら
        if( !empty($_POST['btn_submit']) ) {
            // 選択されているかチェック
            if(empty($question1)) {
                $error_message[] = '問題1を選択してください。';
            }
            if(empty($question2)) {
                $error_message[] = '問題2を選択してください。';
            }
            //未選択がないとき
            if( empty($error_message) ) {
                //データベースの挿入とトランザクションの開始
                $sql = "INSERT INTO xxx (question1,question2) VALUES (:question1,:question2)";
                $stmt = $pdo->prepare($sql);
                $pdo->beginTransaction();
                try{
                    $stmt->bindvalue( ':question1', $question1_db);
                    $stmt->bindvalue( ':question2', $question2_db);
                    $stmt->execute();
                    $pdo->commit();
                    $result = $stmt->fetchAll();
                }catch (PDOException $e) {
                    $pdo->rollBack();
                    throw $e;
                }
            header('Location: xxx');
            exit;
            }
        }
    }catch(PDOException $e) {
        $error_message[] = $e->getMessage();
        header('Content-Type: text/plain; charset=UTF-8', true, 500);
        exit($e->getMessage()); 
    }
    header('Content-Type: text/html; charset=utf-8');
?>
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>example1</title>
            <!-- リンク -->
            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
            <link rel="stylesheet" href="css/reset.css">
        </head>
    <body>
        <main>
            <?php if( !empty($error_message) ){ ?>
                <p class="alert alert-danger col-3" role="alert">
                    <?php foreach( $error_message as $value ){?>
                        <?php echo $value; ?><br>
                    <?php } ?>
                </p>
            <?php } ?>
            <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post" class="p-4">
                <div class="mb-3">
                        <label class="form-label">問題1:三英傑は誰?(複数回答可)</label><br>
                        <input type="checkbox" name="question1[]" value="織田信長" <?php if(isset($question1) && in_array('織田信長',$question1)) { echo "checked";} ?>>織田信長
                        <input type="checkbox" name="question1[]" value="ショパン" <?php if(isset($question1) && in_array('ショパン',$question1)) { echo "checked";} ?>>ショパン
                        <input type="checkbox" name="question1[]" value="毛沢東" <?php if(isset($question1) && in_array('毛沢東',$question1)) { echo "checked";} ?>>毛沢東
                </div>
                <div class="mb-3">
                        <label class="form-label">問題2:日本国民の三大義務は?(複数回答可)</label><br>
                        <input type="checkbox" name="question2[]" value="休息の義務" <?php if(isset($question2) && in_array('休息の義務',$question2)) { echo "checked";} ?>>休息の義務
                        <input type="checkbox" name="question2[]" value="勤労の義務" <?php if(isset($question2) && in_array('勤労の義務',$question2)) { echo "checked";} ?>>勤労の義務
                        <input type="checkbox" name="question2[]" value="納税の義務" <?php if(isset($question2) && in_array('納税の義務',$question2)) { echo "checked";} ?>>納税の義務
                </div>
                <div class="form-group">
                    <input type="submit" name="btn_submit" class="btn btn-primary" value="送信">
                </div>
            </form>
        </main>
    </body>
</html>

解説

<?php
    //セッション開始
    session_start();
    try {
        // データベースに接続
        $pdo = new PDO(
            'mysql:dbname=xxx;host=localhost;charset=utf8',
            'xxx',
            'xxx',
            [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::ATTR_EMULATE_PREPARES =>false
            ]
        );

セッションを開始して、データベースに接続する。
xxx部分は順に、データベース名、ユーザー名、パスワードを入力する。

//変数の定義とシリアライズ
        if(isset($_POST['question1'])){
            $question1 = $_POST['question1'];
            $question1_db = serialize($question1);
        }
        if(isset($_POST['question2'])){
            $question2 = $_POST['question2'];
            $question2_db = serialize($question2);
        }

送信されてきたquestion1question2に値があるとき、$question1$question2にPOST変数を代入する。
また、この2つは配列なのでデータベースに格納できないため、シリアライズをして格納できる形にする。

        //form送信したら
        if( !empty($_POST['btn_submit']) ) {
            // 選択されているかチェック
            if(empty($question1)) {
                $error_message[] = '問題1を選択してください。';
            }
            if(empty($question2)) {
                $error_message[] = '問題2を選択してください。';
            }

送信ボタンがおされたとき$question1$question2が空であったら、$error_message[]に各エラーメッセージを入れる。

            //未選択がないとき
            if( empty($error_message) ) {
                //データベースの挿入とトランザクションの開始
                $sql = "INSERT INTO xxx (question1,question2) VALUES (:question1,:question2)";
                $stmt = $pdo->prepare($sql);
                $pdo->beginTransaction();
                try{
                    $stmt->bindvalue( ':question1', $question1_db);
                    $stmt->bindvalue( ':question2', $question2_db);
                    $stmt->execute();
                    $pdo->commit();
                    $result = $stmt->fetchAll();
                }catch (PDOException $e) {
                    $pdo->rollBack();
                    throw $e;
                }
            header('Location: xxx');
            exit;
            }
        }
    }catch(PDOException $e) {
        $error_message[] = $e->getMessage();
        header('Content-Type: text/plain; charset=UTF-8', true, 500);
        exit($e->getMessage()); 
    }
    header('Content-Type: text/html; charset=utf-8');
?>

エラーメッセージが空、つまり2つの選択肢が選択されているときデータベースにデータを挿入する。
xxxには順に、テーブル名、リダイレクトするファイル名を入力する。今回はファイル自身を設定する。
接続エラー処理の中にトランザクション処理を行ってデータの整合性を保つ。

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>example1</title>
            <!-- リンク -->
            <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css">
            <link rel="stylesheet" href="css/reset.css">
        </head>

デザインテンプレートとしてBootstrapを使用している。

        <main>
            <?php if( !empty($error_message) ){ ?>
                <p class="alert alert-danger col-3" role="alert">
                    <?php foreach( $error_message as $value ){?>
                        <?php echo $value; ?><br>
                    <?php } ?>
                </p>
            <?php } ?>

$error_messageに値が入っているとき、エラーメッセージを表示する。

            <form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post" class="p-4">
                <div class="mb-3">
                        <label class="form-label">問題1:三英傑は誰?(複数回答可)</label><br>
                        <input type="checkbox" name="question1[]" value="織田信長" <?php if(isset($question1) && in_array('織田信長',$question1)) { echo "checked";} ?>>織田信長
                        <input type="checkbox" name="question1[]" value="ショパン" <?php if(isset($question1) && in_array('ショパン',$question1)) { echo "checked";} ?>>ショパン
                        <input type="checkbox" name="question1[]" value="毛沢東" <?php if(isset($question1) && in_array('毛沢東',$question1)) { echo "checked";} ?>>毛沢東
                </div>
                <div class="mb-3">
                        <label class="form-label">問題2:日本国民の三大義務は?(複数回答可)</label><br>
                        <input type="checkbox" name="question2[]" value="休息の義務" <?php if(isset($question2) && in_array('休息の義務',$question2)) { echo "checked";} ?>>休息の義務
                        <input type="checkbox" name="question2[]" value="勤労の義務" <?php if(isset($question2) && in_array('勤労の義務',$question2)) { echo "checked";} ?>>勤労の義務
                        <input type="checkbox" name="question2[]" value="納税の義務" <?php if(isset($question2) && in_array('納税の義務',$question2)) { echo "checked";} ?>>納税の義務
                </div>
                <div class="form-group">
                    <input type="submit" name="btn_submit" class="btn btn-primary" value="送信">
                </div>
            </form>
        </main>
    </body>
</html>

自分自身にデータを送信するformを作成する。
inputタグのname属性は配列にするため、最後に[]をつけるのを忘れずにする。
なお、[]はphpでは記述しなくてよい。
$question1が空の配列ではなくてかつ、$question1に「織田信長」が入っているとき、チェックボックスを選択済みにする。

送信成功したときのデータベース

スクリーンショット 2022-12-26 202226.png

参考文献

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?