記事投稿機能を実装する

今回は、記事を投稿する機能について実装したいと思います。

プログラムの修正

post_edit.phpを以下のように修正します。

admin/post_edit.php
<?php require_once "../system/common_admin.php";?>
<?php
// ホワイトリスト変数の作成
$whitelist = array("send", "mode", "post_title", "post_content");
$request = whitelist($whitelist);

$page_message = ""; // ページに表示するメッセージ
$page_error = ""; // エラーメッセージ

// エラーチェック
if (isset($request["send"])) {
    if ($request["post_title"] == "") {
        $page_error = "記事タイトルを入力してください\n";
    }
}

// 登録実行
if (isset($request["send"]) && $page_error == "") {
    // データベースへ保存
    try {
        $db->beginTransaction();
        $stmt = $db->prepare("INSERT INTO posts (post_title, post_content, post_created) VALUES (?, ?, NOW())");
        $stmt->execute(array($request["post_title"], $request["post_content"]));
        $db->commit();
    } catch (PDOException $e) {
        // エラー発生時
        $db->rollBack();
        exit("クエリの実行に失敗しました");
    }

    // 完了
    $page_message = "登録が完了しました";
}
?>
<?php $page_title = "記事編集";?>
<?php require "header.php";?>
    <p>
      <?php echo he($page_message); ?>
    </p>
    <p class="attention">
      <?php echo he($page_error); ?>
    </p>
    <form action="post_edit.php" method="post">
      <div>
        記事タイトル <span class="attention">[必須]</span><br>
        <input type="text" name="post_title" size="30" value="<?php echo he($request["post_title"]); ?>">
      </div>
      <div>
        記事本文<br>
        <textarea name="post_content" rows="5" cols="20"><?php echo he($request["post_content"]); ?></textarea>
      </div>
      <div>
        <input type="submit" name="send" value="登録する">
      </div>
    </form>
<?php require "footer.php";?>

修正箇所の解説

// ホワイトリスト変数の作成
$whitelist = array("send", "mode", "post_title", "post_content");
$request = whitelist($whitelist);

当機能で使用する変数をホワイトリストで初期化します。

// エラーチェック
if (isset($request["send"])) {
    if ($request["post_title"] == "") {
        $page_error = "記事タイトルを入力してください\n";
    }
}

記事タイトルの必須チェックをします。

    // データベースへ保存
    try {
        $db->beginTransaction();
        $stmt = $db->prepare("INSERT INTO posts (post_title, post_content, post_created) VALUES (?, ?, NOW())");
        $stmt->execute(array($request["post_title"], $request["post_content"]));
        $db->commit();

データベースのデータ更新を行うために、beginTransactionを実行します。
その後、INSERT文を実行しています。(現在日時をpost_createdに流し込むために、NOW()というSQL関数を利用しています。post_updatedについては、テーブルの設定により自動的に更新日時が入ります)

SQLの中で、「?」となっている箇所は、プリペアドステートメントを利用する構文となっています。
SQLに直接変数を流し込むと、SQLインジェクションの攻撃をされる恐れがあります。
SQLに変数を渡す際は、必ずプリペアドステートメントを利用するようにしましょう。

        $stmt = $db->prepare("INSERT INTO posts (post_title, post_content, post_created) VALUES (?, ?, NOW())");

上記で?を使ったSQLステートメントを作成し、

        $stmt->execute(array($request["post_title"], $request["post_content"]));

上記で、?と同数の割り当てたい変数(プレースホルダ)を指定しています。
詳しくは以下をご覧ください。

プリペアドステートメントおよびストアドプロシージャ – Manual

最後に、commitを実行します。

データベースシステムには、データ状況を安定して管理するため、「トランザクション」という機構が実装されています。
トランザクションの仕組みには、「コミット」「ロールバック」が関わってきます。
オートコミットという仕組みを使うと簡単ですが、安定したアプリケーションの開発のため、ぜひ、『トランザクションの機構を常に意識して使う』という方針で考えます。
詳しくは、以下のマニュアルをご覧ください。

PHP: トランザクションおよび自動コミット – Manual

PHP: PDO::beginTransaction – Manual

PHP: PDO::commit – Manual

PHP: PDO::rollBack – Manual

    } catch (PDOException $e) {
        // エラー発生時
        $db->rollBack();
        exit("クエリの実行に失敗しました");
    }

例外発生時はrollBackして終了します。

    // 完了
    $page_message = "登録が完了しました";

登録完了メッセージをセットします。

      <div>
        記事タイトル <span class="attention">[必須]</span><br>
        <input type="text" name="post_title" size="30" value="<?php echo he($request["post_title"]); ?>">
      </div>
      <div>
        記事本文<br>
        <textarea name="post_content" rows="5" cols="20"><?php echo he($request["post_content"]); ?></textarea>
      </div>
      <div>
        <input type="submit" name="send" value="登録する">
      </div>

各入力項目に初期値をセットするようにしました。

以上で管理画面の記事投稿機能が実装できました。
この段階ではまだ、登録後の処理が不十分ですので、引き続き進めていきます。
今回のコンテンツについては以下よりダウンロードできます。

step3-050.zip

このページをシェア Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn