# 投稿・削除が完了したことをユーザに知らせる

ユーザビリティ向上のため、投稿・削除が成功、失敗した際にそれぞれテキストを表示することでユーザに情報を伝えます。

以下のようにテキストが表示される状態を目指します。

投稿

# 本セクションの流れ

  1. セッションを制御してテキストを処理する。
  2. index.php の中でテキストを表示させる。

# 1. セッションを制御してテキストを処理する。

セッション変数を利用し、ページ遷移後も値(テキスト)を変数に保持させます。

~~/src/insert_message.php に以下のコードを追加します。






















 
 




 
 
 





~~

// 投稿をデータベースへ保存する処理
if ($is_valid_auther_name && $is_valid_message) {
  if ($input_author_name === '') {
    $input_author_name = '匿名さん';
  }

  // INSERT クエリを作成する
  // :author_name、:message はプレースホルダという。後で $stmt->bindValue を使用して値をセットするときのニックネームのようなもの。自分で決められる。
  $query = 'INSERT INTO posts (author_name, message) VALUES (:author_name, :message)';

  // SQL 実行の準備 (実行はされない)
  $stmt = $dbh->prepare($query);

  // プレースホルダに値をセットする
  $stmt->bindValue(':author_name', $input_author_name, PDO::PARAM_STR);
  $stmt->bindValue(':message', $input_message, PDO::PARAM_STR);

  // クエリを実行する
  $stmt->execute();
  $_SESSION['action_success_text'] = '投稿しました';
  $_SESSION['action_error_text'] = '';
  $_SESSION['input_error_author_name'] = '';
  $_SESSION['input_error_message'] = '';
  $_SESSION['input_pre_author_name'] = '';
  $_SESSION['input_pre_message'] = '';
} else {
  $_SESSION['action_success_text'] = '';
  $_SESSION['action_error_text'] = '入力内容を確認してください';
}

header('Location: /');
exit();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

投稿者名、投稿内容のバリデーションが通った場合に、投稿完了のテキスト「投稿しました」を$_SESSION['action_success_text']に格納し、バリデーションが通らなかった場合に、エラー内容の文字列「入力内容を確認してください」を$_SESSION['action_error_text']に格納します。

~~/src/delete_message.php に以下のコードを追加します。







 
 
 
 
 





<?php

if (isset($_POST['id']) && $_POST['id']) {
  $stmt = $dbh->prepare('DELETE FROM posts WHERE id = :id');
  $stmt->bindValue(':id', $_POST['id'], PDO::PARAM_INT);
  $stmt->execute();
  $_SESSION['action_success_text'] = '削除が完了しました';
  $_SESSION['action_error_text'] = '';
} else {
  $_SESSION['action_success_text'] = '';
  $_SESSION['action_error_text'] = 'id がありません';
}

header('Location: /');
exit();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

isset($_POST['id']) && $_POST['id'] の条件によって削除完了時と失敗時にそれぞれ表示するテキストを格納しています。

~~/src/session_values.php に以下のコードを追加します。



 
 






 
 
 
 
 
 
 
 
 





















<?php
// ページ内で使用する変数を初期化する
$messages['action_success_text'] = '';
$messages['action_error_text'] = '';
$messages['input_error_author_name'] = '';
$messages['input_error_message'] = '';
$messages['input_pre_author_name'] = '';
$messages['input_pre_message'] = '';

// ページ内で使用する変数にセッションから代入する
if (isset($_SESSION['action_success_text'])) {
  $messages['action_success_text'] = $_SESSION["action_success_text"];
  unset($_SESSION["action_success_text"]);
}

if (isset($_SESSION['action_error_text'])) {
  $messages['action_error_text'] = $_SESSION["action_error_text"];
  unset($_SESSION["action_error_text"]);
}

if (isset($_SESSION['input_error_author_name'])) {
  $messages['input_error_author_name'] = $_SESSION["input_error_author_name"];
  unset($_SESSION["input_error_author_name"]);
}

if (isset($_SESSION['input_error_message'])) {
  $messages['input_error_message'] = $_SESSION["input_error_message"];
  unset($_SESSION["input_error_message"]);
}

if (isset($_SESSION['input_pre_author_name'])) {
  $messages['input_pre_author_name'] = $_SESSION["input_pre_author_name"];
  unset($_SESSION["input_pre_author_name"]);
}

if (isset($_SESSION['input_pre_message'])) {
  $messages['input_pre_message'] = $_SESSION["input_pre_message"];
  unset($_SESSION["input_pre_message"]);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

~~/src/insert_message.php~~/src/delete_message.phpで更新された変数をそれぞれ、$messages[] へ代入します。

# 2. index.php の中でテキストを表示させる。

~~/public/index.php








 
 
 
 
 
 






~~~
<body>
  <div class="page-cover">

    <p class="page-title">ひとこと掲示板</p>
    <hr class="page-divider" />

    <?php if ($messages['action_success_text'] !== '') { ?>
      <div class="action-success-area"><?php echo $messages['action_success_text']; ?></div>
    <?php } ?>
    <?php if ($messages['action_error_text'] !== '') { ?>
      <div class="action-failed-area"><?php echo $messages['action_error_text']; ?></div>
    <?php } ?>

    <div class="form-cover">
      <form action="/" method="post">
        <div class="form-input-title">投稿者ニックネーム</div>
~~~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

~~/src/session_values.php で代入された文字列を表示します。

# 動作確認

  • 投稿完了の挙動

投稿

  • 投稿完了
投稿しました
  • 投稿エラー
入力内容確認しろ - 削除の挙動

削除

  • 削除完了
削除が完了しました

# 最終的なコードとファイル構成

~~/public/index.php

<?php
session_start();
require_once(__DIR__ . '/../src/db_connect.php');

if (isset($_POST['action_type']) && $_POST['action_type']) {
  if ($_POST['action_type'] === 'insert') {
    require(__DIR__ . '/../src/insert_message.php');
  } elseif ($_POST['action_type'] === 'delete') {
    require(__DIR__ . '/../src/delete_message.php');
  }
}

require(__DIR__ . '/../src/session_values.php');

$stmt = $dbh->query('SELECT * FROM posts ORDER BY created_at DESC;');
$message_length = $stmt->rowCount();

function convertTz($datetime_text)
{
  $datetime = new DateTime($datetime_text);
  $datetime->setTimezone(new DateTimeZone('Asia/Tokyo'));
  return $datetime->format('Y/m/d H:i:s');
}
?>
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="robots" content="noindex" />
  <title>ひとこと掲示板</title>
  <link rel="stylesheet" href="./assets/main.css" />
</head>

<body>
  <div class="page-cover">
    <p class="page-title">ひとこと掲示板</p>
    <hr class="page-divider" />

    <?php if ($messages['action_success_text'] !== '') { ?>
      <div class="action-success-area"><?php echo $messages['action_success_text']; ?></div>
    <?php } ?>
    <?php if ($messages['action_error_text'] !== '') { ?>
      <div class="action-failed-area"><?php echo $messages['action_error_text']; ?></div>
    <?php } ?>

    <div class="form-cover">
      <form action="/" method="post">
        <div class="form-input-title">投稿者ニックネーム</div>
        <input type="text" name="author_name" maxlength="40" value="<?php echo htmlspecialchars($messages['input_pre_author_name'], ENT_QUOTES); ?>" class="input-author-name" />
        <?php if ($messages['input_error_author_name'] !== '') { ?>
          <div class="form-input-error">
            <?php echo $messages['input_error_author_name']; ?>
          </div>
        <?php } ?>
        <div class="form-input-title">投稿内容<small>(必須)</small></div>
        <textarea name="message" class="input-message"><?php echo htmlspecialchars($messages['input_pre_message'], ENT_QUOTES); ?></textarea>
        <?php if ($messages['input_error_message'] !== '') { ?>
          <div class="form-input-error">
            <?php echo $messages['input_error_message']; ?>
          </div>
        <?php } ?>
        <input type="hidden" name="action_type" value="insert" />
        <button type="submit" class="input-submit-button">投稿する</button>
      </form>
    </div>
    <hr class="page-divider" />
    <div class="message-list-cover">
      <small>
        <?php echo $message_length; ?> 件の投稿
      </small>

      <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { ?>
        <?php $lines = explode("\n", $row['message']); ?>
        <div class="message-item">
          <div class="message-title">
            <div><?php echo htmlspecialchars($row['author_name'], ENT_QUOTES); ?></div>
            <small><?php echo convertTz($row['created_at']); ?></small>
            <div class="spacer"></div>
            <form action="/" method="post" style="text-align:right">
              <input type="hidden" name="id" value="<?php echo $row['id']; ?>" />
              <input type="hidden" name="action_type" value="delete" />
              <button type="submit" class="message-delete-button">削除</button>
            </form>
          </div>
          <?php foreach ($lines as $line) { ?>
            <p class="message-line"><?php echo htmlspecialchars($line, ENT_QUOTES); ?></p>
          <?php } ?>
        </div>
      <?php } ?>
    </div>
  </div>
</body>

</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

~~/src/insert_message.php

<?php

/**
 * 両端の空白を除去する関数です。マルチバイトを含みます。
 * 参考 https://qiita.com/fallout/items/a13cebb07015d421fde3
 */
function mbTrim($pString)
{
  return preg_replace('/\A[\p{Cc}\p{Cf}\p{Z}]++|[\p{Cc}\p{Cf}\p{Z}]++\z/u', '', $pString);
}

// 入力値を確認する(投稿者)
$is_valid_auther_name = true;
$input_author_name = '';
if (isset($_POST['author_name'])) {
  $input_author_name = mbTrim(str_replace("\r\n", "\n", $_POST['author_name']));
  $_SESSION['input_pre_author_name'] = $_POST['author_name'];
} else {
  $is_valid_auther_name = false;
}

if ($is_valid_auther_name && mb_strlen($input_author_name) > 30) {
  $is_valid_auther_name = false;
  $_SESSION['input_error_author_name'] = 'ニックネームは 30 文字以内で入力してください。(現在 ' . mb_strlen($input_author_name) . ' 文字)';
}

// 入力値を確認する(投稿内容)
$is_valid_message = true;
$input_message = '';
if (isset($_POST['message'])) {
  $input_message = mbTrim(str_replace("\r\n", "\n", $_POST['message']));
  $_SESSION['input_pre_message'] = $_POST['message'];
} else {
  $is_valid_message = false;
}

if ($is_valid_message && $input_message === '') {
  $is_valid_message = false;
  $_SESSION['input_error_message'] = '投稿内容の入力は必須です。';
}

if ($is_valid_message && mb_strlen($input_message) > 1000) {
  $is_valid_message = false;
  $_SESSION['input_error_message'] = '投稿内容は 1000 文字以下で入力してください。(現在 ' . mb_strlen($input_message) . ' 文字)';
}

// 投稿をデータベースへ保存する処理
if ($is_valid_auther_name && $is_valid_message) {
  if ($input_author_name === '') {
    $input_author_name = '匿名さん';
  }

  // INSERT クエリを作成する
  // :author_name、:message はプレースホルダという。後で $stmt->bindValue を使用して値をセットするときのニックネームのようなもの。自分で決められる。
  $query = 'INSERT INTO posts (author_name, message) VALUES (:author_name, :message)';

  // SQL 実行の準備 (実行はされない)
  $stmt = $dbh->prepare($query);

  // プレースホルダに値をセットする
  $stmt->bindValue(':author_name', $input_author_name, PDO::PARAM_STR);
  $stmt->bindValue(':message', $input_message, PDO::PARAM_STR);

  // クエリを実行する
  $stmt->execute();
  $_SESSION['action_success_text'] = '投稿しました';
  $_SESSION['action_error_text'] = '';
  $_SESSION['input_error_author_name'] = '';
  $_SESSION['input_error_message'] = '';
  $_SESSION['input_pre_author_name'] = '';
  $_SESSION['input_pre_message'] = '';
} else {
  $_SESSION['action_success_text'] = '';
  $_SESSION['action_error_text'] = '入力内容を確認してください';
}

header('Location: /');
exit();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

~~/src/delete_message.php

<?php

if (isset($_POST['id']) && $_POST['id']) {
  $stmt = $dbh->prepare('DELETE FROM posts WHERE id = :id');
  $stmt->bindValue(':id', $_POST['id'], PDO::PARAM_INT);
  $stmt->execute();
  $_SESSION['action_success_text'] = '削除が完了しました';
  $_SESSION['action_error_text'] = '';
} else {
  $_SESSION['action_success_text'] = '';
  $_SESSION['action_error_text'] = 'id がありません';
}

header('Location: /');
exit();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

~~/src/session_values.php

<?php
// ページ内で使用する変数を初期化する
$messages['action_success_text'] = '';
$messages['action_error_text'] = '';
$messages['input_error_author_name'] = '';
$messages['input_error_message'] = '';
$messages['input_pre_author_name'] = '';
$messages['input_pre_message'] = '';

// ページ内で使用する変数にセッションから代入する
if (isset($_SESSION['action_success_text'])) {
    $messages['action_success_text'] = $_SESSION["action_success_text"];
    unset($_SESSION["action_success_text"]);
}

if (isset($_SESSION['action_error_text'])) {
    $messages['action_error_text'] = $_SESSION["action_error_text"];
    unset($_SESSION["action_error_text"]);
}

if (isset($_SESSION['input_error_author_name'])) {
    $messages['input_error_author_name'] = $_SESSION["input_error_author_name"];
    unset($_SESSION["input_error_author_name"]);
}

if (isset($_SESSION['input_error_message'])) {
    $messages['input_error_message'] = $_SESSION["input_error_message"];
    unset($_SESSION["input_error_message"]);
}

if (isset($_SESSION['input_pre_author_name'])) {
    $messages['input_pre_author_name'] = $_SESSION["input_pre_author_name"];
    unset($_SESSION["input_pre_author_name"]);
}

if (isset($_SESSION['input_pre_message'])) {
    $messages['input_pre_message'] = $_SESSION["input_pre_message"];
    unset($_SESSION["input_pre_message"]);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

ファイル構成

.
├── docker-compose.yml
├── php
│   └── Dockerfile
├── public
│   ├── assets
│   │   └── main.css
│   └── index.php
└── src
    ├── db_connect.php
    ├── delete_message.php
    ├── insert_message.php
    └── session_values.php
1
2
3
4
5
6
7
8
9
10
11
12
13