PHPプログラミング

最終更新日:
公開日:

ワークショップ

ひと言掲示板を作る(19)

投稿メッセージの編集ページを作る

「ひと言掲示板」に書き込まれた投稿を、管理ページから編集する機能を実装します。

この記事のポイント

  • GET形式のパラメータはリンクの後ろに「?」で区切って指定する
  • SQLのSELECT文にWHERE句を指定して取得データを絞り込む

目次

投稿されたメッセージを編集する

前回までは、ひと言掲示板の管理ページに投稿データをCSV形式でダウンロードする機能を実装してきました。
今回からは投稿されたメッセージを編集する機能を実装していきます。

「編集」を押すと、次のように編集ページが開きます。

編集ページは少し工程が多いため、今回と次回の2回に分けて作成していきます。

「ひと言掲示板を作る」の概要については「ひと言掲示板を作る」をご覧ください。
デモはこちら

前回までに作成したコードはこちら:Github

編集ページを作成する

編集ページは管理ページとは独立したページとして作成します。
次のように、管理ページで「編集」が押されると投稿IDを渡して編集ページを開き、編集ページで編集完了するか、キャンセルすると管理ページに戻るような構成です。

まずは、編集ページとなる「edit.php」を作成しましょう。
index.php」を複製して、ファイル名を「edit.php」に変更してください。

複製したら、edit.phpを開いて「// データベースに接続」でデータベースに接続するコードより下から「// データベースの接続を閉じる」までの間のコードを一旦削除してください。

edit.php

<?php

// データベースの接続情報
define( 'DB_HOST', 'localhost');
define( 'DB_USER', 'root');
define( 'DB_PASS', 'password');
define( 'DB_NAME', 'board');

// タイムゾーン設定
date_default_timezone_set('Asia/Tokyo');

// 変数の初期化
$current_date = null;
$message = array();
$message_array = array();
$success_message = null;
$error_message = array();
$pdo = null;
$stmt = null;
$res = null;
$option = null;

session_start();

// データベースに接続
try {

	$option = array(
		PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
		PDO::MYSQL_ATTR_MULTI_STATEMENTS => false
	);
	$pdo = new PDO('mysql:charset=UTF8;dbname='.DB_NAME.';host='.DB_HOST , DB_USER, DB_PASS, $option);

} catch(PDOException $e) {

	// 接続エラーのときエラー内容を取得する
	$error_message[] = $e->getMessage();
}

////////////////////////////////
// ここにあるコードは全て削除
////////////////////////////////

// データベースの接続を閉じる
$pdo = null;

?>
<!DOCTYPE html>

---- 省略 ----

ログインセッションを確認する

編集ページはダウンロードページと同様に管理者しかアクセスできないページです。
そこで、ログインセッションがあるかを確認しましょう。

edit.php

<?php

// データベースの接続情報
define( 'DB_HOST', 'localhost');
define( 'DB_USER', 'root');
define( 'DB_PASS', 'password');
define( 'DB_NAME', 'board');

// タイムゾーン設定
date_default_timezone_set('Asia/Tokyo');

// 変数の初期化
$current_date = null;
$message = array();
$message_array = array();
$success_message = null;
$error_message = array();
$pdo = null;
$stmt = null;
$res = null;
$option = null;

session_start();

// 管理者としてログインしているか確認
if( empty($_SESSION['admin_login']) || $_SESSION['admin_login'] !== true ) {

	// ログインページへリダイレクト
	header("Location: ./admin.php");
	exit;
}

// データベースに接続
try {

	$option = array(
		PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
		PDO::MYSQL_ATTR_MULTI_STATEMENTS => false
	);
	$pdo = new PDO('mysql:charset=UTF8;dbname='.DB_NAME.';host='.DB_HOST , DB_USER, DB_PASS, $option);

} catch(PDOException $e) {

	// 接続エラーのときエラー内容を取得する
	$error_message[] = $e->getMessage();
}

---- 省略 ----

もしログインしていない状態でアクセスするとセッションがないため、header関数で管理ページ「admin.php」に戻ります。

ログインセッションの確認に続いて、編集する投稿データを特定するための投稿IDが渡されているかを確認します。
赤字になっているコードをデータベースの接続と解除のコードの間に記述してください。

edit.php

<?php

---- 省略 ----

session_start();

// データベースに接続
try {

	$option = array(
		PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
		PDO::MYSQL_ATTR_MULTI_STATEMENTS => false
	);
	$pdo = new PDO('mysql:charset=UTF8;dbname='.DB_NAME.';host='.DB_HOST , DB_USER, DB_PASS, $option);

} catch(PDOException $e) {

	// 接続エラーのときエラー内容を取得する
	$error_message[] = $e->getMessage();
}

if( !empty($_GET['message_id']) ) {

	// 投稿を取得するコードが入る

}

// データベースの接続を閉じる
$pdo = null;

---- 省略 ----

GETパラメータで投稿IDである「message_id」が渡されていたら、if文の中で投稿IDに該当する投稿(メッセージ)をデータベースから取得します。

edit.php

<?php

---- 省略 ----

if( !empty($_GET['message_id']) ) {

	// SQL作成
	$stmt = $pdo->prepare("SELECT * FROM message WHERE id = :id");

	// 値をセット
	$stmt->bindValue( ':id', $_GET['message_id'], PDO::PARAM_INT);

	// SQLクエリの実行
	$stmt->execute();

	// 表示するデータを取得
	$message_data = $stmt->fetch();

	// 投稿データが取得できないときは管理ページに戻る
	if( empty($message_data) ) {
		header("Location: ./admin.php");
		exit;
	}
}

// データベースの接続を閉じる
$stmt = null;
$pdo = null;

---- 省略 ----

追記したコードでは、受け取った投稿IDをPDOのプリペアドステートメントを使い、データベースから投稿データを取得しています。
プリペアドステートメントのSQLではプレースホルダー「:id」を設置し、その後にbindValueメソッド$message_idに入っている投稿IDをセットします。

投稿データを取得できたら、連想配列形式で$message_dataにデータを代入します。
もし投稿データが見つからなかった場合は$message_dataが空になるため、header関数で管理ページにリダイレクトします。

ここまでで編集する投稿メッセージのデータを取得することができました。
続いて、取得したデータを使って編集ページを表示していきます。

編集ページのHTMLを作る

続いて、「index.php」を複製した投稿フォームのコードをベースに編集ページを作成していきましょう。
まずは不要なコードを削除していきます。

edit.php」を開いて、次の赤字になっているコードを削除してください。

edit.php

---- 省略 ----

<body>
<h1>ひと言掲示板</h1>
<?php if( !empty($success_message) ): ?>
	<p class="success_message"><?php echo $success_message; ?></p>
<?php endif; ?>
<?php if( !empty($error_message) ): ?>
	<ul class="error_message">
		<?php foreach( $error_message as $value ): ?>
			<li>・<?php echo $value; ?></li>
		<?php endforeach; ?>
	</ul>
<?php endif; ?>
<form method="post">
	<div>
		<label for="view_name">表示名</label>
		<input id="view_name" type="text" name="view_name" value="<?php if( !empty($_SESSION['view_name']) ){ echo htmlspecialchars( $_SESSION['view_name'], ENT_QUOTES, 'UTF-8'); } ?>">
	</div>
	<div>
		<label for="message">ひと言メッセージ</label>
		<textarea id="message" name="message"></textarea>
	</div>
	<input type="submit" name="btn_submit" value="書き込む">
</form>
<hr>
<section>
<?php if( !empty($message_array) ){ ?>
<?php foreach( $message_array as $value ){ ?>
<article>
	<div class="info">
		<h2><?php echo htmlspecialchars( $value['view_name'], ENT_QUOTES, 'UTF-8'); ?></h2>
		<time><?php echo date('Y年m月d日 H:i', strtotime($value['post_date'])); ?></time>
	</div>
	<p><?php echo nl2br( htmlspecialchars($value['message'], ENT_QUOTES, 'UTF-8') ); ?></p>
</article>
<?php } ?>
<?php } ?>
</section>
</body>
</html>

削除した後のコードは次のようになります。

edit.php

---- 省略 ----

<body>
<h1>ひと言掲示板</h1>
<?php if( !empty($error_message) ): ?>
	<ul class="error_message">
		<?php foreach( $error_message as $value ): ?>
			<li>・<?php echo $value; ?></li>
		<?php endforeach; ?>
	</ul>
<?php endif; ?>
<form method="post">
	<div>
		<label for="view_name">表示名</label>
		<input id="view_name" type="text" name="view_name" value="">
	</div>
	<div>
		<label for="message">ひと言メッセージ</label>
		<textarea id="message" name="message"></textarea>
	</div>
	<input type="submit" name="btn_submit" value="書き込む">
</form>
</body>
</html>

続いて、編集ページであることがわかるようにページタイトルを編集します。

edit.php

---- 省略 ----

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ひと言掲示板 管理ページ(投稿の編集)</title>
<style>

---- 省略 ----

</style>
</head>
<body>
<h1>ひと言掲示板 管理ページ(投稿の編集)</h1>

---- 省略 ----

先ほど取得したメッセージのデータを、フォームに表示するようにしていきます。
「表示名」と「メッセージ」にそれぞれ出力するコードを追記します。

edit.php

---- 省略 ----

<body>
<h1>ひと言掲示板 管理ページ(投稿の編集)</h1>
<?php if( !empty($error_message) ): ?>
	<ul class="error_message">
		<?php foreach( $error_message as $value ): ?>
			<li>・<?php echo $value; ?></li>
		<?php endforeach; ?>
	</ul>
<?php endif; ?>
<form method="post">
	<div>
		<label for="view_name">表示名</label>
		<input id="view_name" type="text" name="view_name" value="<?php if( !empty($message_data['view_name']) ){ echo $message_data['view_name']; } ?>">
	</div>
	<div>
		<label for="message">ひと言メッセージ</label>
		<textarea id="message" name="message"><?php if( !empty($message_data['message']) ){ echo $message_data['message']; } ?></textarea>
	</div>
	<input type="submit" name="btn_submit" value="書き込む">
</form>
</body>
</html>

どちらもempty関数で値があることを事前に確認し、値があるときのみ出力します。
続いて、編集をキャンセルする場合のリンクを追加します。

edit.php

---- 省略 ----

<form method="post">
	<div>
		<label for="view_name">表示名</label>
		<input id="view_name" type="text" name="view_name" value="<?php if( !empty($message_data['view_name']) ){ echo $message_data['view_name']; } ?>">
	</div>
	<div>
		<label for="message">ひと言メッセージ</label>
		<textarea id="message" name="message"><?php if( !empty($message_data['message']) ){ echo $message_data['message']; } ?></textarea>
	</div>
	<a class="btn_cancel" href="admin.php">キャンセル</a>
	<input type="submit" name="btn_submit" value="書き込む">
</form>
</body>
</html>

ついでに、「書き込む」ボタンのラベルを「更新」に変更しておきましょう。

edit.php

<input type="submit" name="btn_submit" value="更新">

続いて、編集内容を登録するときにどの投稿が対象になるか分かるように投稿IDをinput要素にセットして設置します。
この値は誤って編集することが無いように、input要素type属性を「hidden」にして非表示の項目にしておきましょう。

edit.php

---- 省略 ----

<form method="post">
	<div>
		<label for="view_name">表示名</label>
		<input id="view_name" type="text" name="view_name" value="<?php if( !empty($message_data['view_name']) ){ echo $message_data['view_name']; } ?>">
	</div>
	<div>
		<label for="message">ひと言メッセージ</label>
		<textarea id="message" name="message"><?php if( !empty($message_data['message']) ){ echo $message_data['message']; } ?></textarea>
	</div>
	<a class="btn_cancel" href="admin.php">キャンセル</a>
	<input type="submit" name="btn_submit" value="更新">
	<input type="hidden" name="message_id" value="<?php if( !empty($message_data['id']) ){ echo $message_data['id']; } ?>">
</form>

先ほど追加した「キャンセル」のリンクに、ボタンのような表示になるようCSSを追記します。
style属性の中であればどこに記述しても大丈夫です。
次の例では「掲示板エリア」というコメントの上に追記しています。

edit.php

---- 省略 ----

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ひと言掲示板 管理ページ(投稿の編集)</title>
<style>

---- 省略 ----

.success_message,
.error_message li {
	font-size: 86%;
	line-height: 1.6em;
}

.btn_cancel {
	display: inline-block;
	margin-right: 10px;
	padding: 10px 20px;
	color: #555;
	font-size: 86%;
	border-radius: 5px;
	border: 1px solid #999;
}
.btn_cancel:hover {
	color: #999;
	border-color: #999;
	text-decoration: none;
}


/*-----------------------------------
掲示板エリア
-----------------------------------*/

---- 省略 ----

</style>
</head>

---- 省略 ----

edit.php」を編集してきましたが、この後は「admin.php」から編集ページに移動できるようにリンクを繋げていきます。
ここまでの内容を保存して、次に進んでください。

管理ページと編集ページを繋げる

管理ページ「admin.php」と編集ページ「edit.php」をリンクで繋げましょう。

admin.php」を開いて、投稿を取得するSELECT文のカラム指定を「view_name,message,post_date」から「*」へ修正してください。
この修正で、取得した投稿データに投稿IDが含まれるようになります。

admin.php

---- 省略 ----

if( !empty($pdo) ) {

	// メッセージのデータを取得する
	$sql = "SELECT * FROM message ORDER BY post_date DESC";
	$message_array = $pdo->query($sql);
}

// データベースの接続を閉じる
$stmt = null;
$pdo = null;

---- 省略 ----

続いて、投稿一覧を表示するエリアに赤字のリンクを追記してください。
ここでは、この後に作成する削除ページ「delete.php」のリンクもついでに設定してしまいます。

admin.php

---- 省略 ----

<?php if( !empty($message_array) ){ ?>
<?php foreach( $message_array as $value ){ ?>
<article>
	<div class="info">
		<h2><?php echo htmlspecialchars($value['view_name'], ENT_QUOTES, 'UTF-8'); ?></h2>
		<time><?php echo date('Y年m月d日 H:i', strtotime($value['post_date'])); ?></time>
		<p><a href="edit.php?message_id=<?php echo $value['id']; ?>">編集</a>  <a href="delete.php?message_id=<?php echo $value['id']; ?>">削除</a></p>
	</div>
	<p><?php echo nl2br( htmlspecialchars( $value['message'], ENT_QUOTES, 'UTF-8') ); ?></p>
</article>
<?php } ?>
<?php } ?>

---- 省略 ----

a要素href属性に編集ページのファイル名を指定し、さらに「?」で区切った上でGETパラメータとして投稿ID「message_id」を付与します。
これで、リンクをクリックしたときに投稿IDも同時に渡されるので、編集ページが開いた後にこのパラメータから投稿データを取得することができるようになります。

form要素とPOST形式とは異なるデータの送信方法ですが、投稿IDのような機密性がないデータについてはGET形式で渡すことが一般的です。

こちらのリンクについても、CSSを追記します。

admin.php

---- 省略 ----

	.info {
		margin-bottom: 10px;
	}
	.info h2 {
		display: inline-block;
		margin-right: 10px;
		color: #222;
		line-height: 1.6em;
		font-size: 86%;
	}
	.info time {
		color: #999;
		line-height: 1.6em;
		font-size: 72%;
	}
	.info p {
		display: inline-block;
		line-height: 1.6em;
		font-size: 86%;
	}
	article p {
		color: #555;
		font-size: 86%;
		line-height: 1.6em;
	}

---- 省略 ----

ここまでの編集内容を保存して、ブラウザで「admin.php」から開いて確認してみましょう。
投稿に新しく設置した「編集」のリンクをクリックしてください。

すると、次のように投稿メッセージの編集ページが表示されます。

現時点では投稿データの取得と表示しか作っていないため、まだ内容を編集しても何も起こりません。
「キャンセル」ボタンで一覧ページに戻れることを確認してみてください。

今回はここまでとなります。
次回は引き続き、編集した内容をデータベースに保存する機能を追加していきます。

今回作成したコード:Github