今回は、記事を投稿する機能について実装したいと思います。
プログラムの修正
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
} 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>
各入力項目に初期値をセットするようにしました。
以上で管理画面の記事投稿機能が実装できました。
この段階ではまだ、登録後の処理が不十分ですので、引き続き進めていきます。
今回のコンテンツについては以下よりダウンロードできます。