(第3回)PHPでSNSを作成してみる

(第3回)PHPでSNSを作成してみる

目次

はじめに
エラーメッセージの表示方法
投稿内容の表示
ファイルの分割
見栄え改善
次回予告

はじめに

前回は投降した内容がDBに保存されるまでの流れを紹介しました。
今回は、投稿内容を表示する機能と、見栄えに関して、もう少し見やすいものにしていこうと思います。

エラーメッセージの表示方法

前回の最後にエラーがあった際に、タイトルの上に、var_dump関数で取得したエラー内容を
表示する機能を実装していました。
これでもエラー内容は伝わるのですが、見栄えの問題ともう少しシンプルに内容をお伝えできる方法があるので、
そちらをまず実装していきたいと思います。

// エラーチェック処理を追加
<form action="connectbbs.php" method="post">
<?php if (count($errors)): ?>
<ul class="error_list">
    <?php foreach ($errors as $error): ?>
    <li>
        <?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?>
    </li>
    <?php endforeach; ?>
</ul>
<?php endif; ?>
 名前: <input type="text" name="name" /><br>
 内容: <input type="text" name="comment" size="60" /><br>
 <input type="submit" name="submit" value="送信" />
</form>

まず上部に出ていたものをタイトルと投稿フォームの間に出力できるようにします。
formタグの中に、コードを書くことで、上記を実現させます。
コードの内容としては、エラー内容を配列に入れているので、こちらをリスト形式で出力できるようにしています。
出力の結果が下記画像になります(名前とタイトルを入力せずに投稿してみました)。

var_dump関数の処理が残っているので、両方表示されていますが、エラー内容に関してわかりやすく表示できています。
エラーのメッセージに関しては、前回作成したものになりますので、表示内容等は下記のコードを参考にしてください。

//POSTなら保存処理
if($_SERVER['REQUEST_METHOD'] === 'POST') {
    //名前のチェック
    $name = null;
    //名前がnullでないことをチェック
    if(!isset($_POST['name']) || !strlen($_POST['name'])) {
        $errors['name'] = '名前を入力してください';
    } else if (strlen($_POST['name']) > 40) {
        $errors['name'] = '名前は40文字以内で入力してください';
    } else {
        $name = $_POST['name'];
    }
    //コメントのチェック
    $comment = null;
    //名前がnullでないことをチェック
    if(!isset($_POST['comment']) || !strlen($_POST['comment'])) {
        $errors['comment'] = 'コメントを入力してください';
    } else if (strlen($_POST['comment']) > 200) {
        $errors['comment'] = 'コメントは200文字以内で入力してください';
    } else {
        $comment = $_POST['comment'];
    }

エラーメッセージに関して、一部装飾を入れてますが、今回記事の最後でCSSの編集をしているので、そこで紹介させていただきます。
また、上記を記載したことで必要なくなったvar_dump関数の処理は取り除きます。
下記のハイライト部分が削除する処理となります。

//エラーがなければ保存
if (count($errors) === 0) {
    //保存するためのSQL分を作成
    $sql ='INSERT INTO post(pname, comment, created_day)VALUES("'
        .mysqli_real_escape_string($mysql, $name).'","'
        .mysqli_real_escape_string($mysql, $comment).'",\''
        .date('Y-m-d H:i:s').'\')';
    //保存する
    mysqli_query($mysql, $sql);
    //接続を閉じる
    mysqli_close($mysql);
    header('location: http://' .$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
}else{
    var_dump($errors);
    //接続を閉じる
    mysqli_close($mysql);
}

投稿内容の表示

前回までは、名前と内容を投稿しても、DBに保存されるだけで、投稿内容が目に見えてわからなかったため、
掲示板と呼べないものでした。
今回は、投稿内容が共有できるようにしていきたいと思います。

<body>
    <h1>BBS</h1>
    <form action="bbs.php" method="post">
        <!-- エラーがあれば表示 -->
        <?php if (count($errors)): ?>
        <ul class="error_list">
            <?php foreach ($errors as $error): ?>
            <li>
                <?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?>
            </li>
            <?php endforeach; ?>
        </ul>
        <?php endif; ?>
        名前: <input type="text" name="name" /><br>
        内容: <input type="text" name="comment" size="60" /><br>
        <input type="submit" name="submit" value="送信" />
    </form>
    <!-- 取得内容を表示 -->
    <?php if (count($posts) > 0): ?>
    <ul>
        <?php foreach ($posts as $post): ?>
        <li>
            <?php echo htmlspecialchars($post['pname'], ENT_QUOTES, 'UTF-8'); ?>
            <?php echo htmlspecialchars($post['comment'], ENT_QUOTES, 'UTF-8'); ?>
            - <?php echo htmlspecialchars($post['created_day'], ENT_QUOTES, 'UTF-8'); ?>
        </li>
        <?php endforeach; ?>
    </ul>
    <?php endif; ?>
</body>

上記が完成のコードとなります。
Formタグの下にDBからの取得結果を表示することで、DBの該当テーブル上にある名前から投稿日時までの内容を表示することが出来ます。
処理に関しては、エラーメッセージの表示で行っていた処理とほとんど同じです。
では、実際に動作させてみた結果が下記になります。

問題なく、必要項目が表示されています。
どんどん投稿することで、情報が蓄積されて、共有内容も多くなっていく仕組みになります。
(投稿内容がかなり多くなると検索機能がないとつらいですね…)

ファイルの分割

一つのファイルにかなり処理が増えてしまったので、前回も分割したのですが、処理の整理も含めて、
再分割します。
下記のような構成にします。

  • bbs.php    : phpのサーバサイド処理をメインに行っているファイル
  • bbs_view.php  : WEBで表示されるHTML部分をメインにしたファイル(一部PHPの処理もあり)
  • bbs.css     : デザインファイル
//bbs.php

<?php
    //DBに接続
    $mysql = mysqli_connect('localhost', 'root', 'AoFLS030cztQMGzd6i3e', 'fp_bbs');
    if (!$mysql) {
        exit('DB接続エラー');
    } 
    mysqli_set_charset($mysql, 'utf8');
    //DBの選択
    $result = mysqli_select_db($mysql, 'fp_bbs');
    if (!$result) {
        exit('DB選択エラー');
    } 
    $errors = array();

    //POSTなら保存処理
    if($_SERVER['REQUEST_METHOD'] === 'POST') {
        //名前のチェック
        $name = null;
        //名前がnull出ないことをチェック
        if(!isset($_POST['name']) || !strlen($_POST['name'])) {
            $errors['name'] = '名前を入力してください';
        } else if (strlen($_POST['name']) > 40) {
            $errors['name'] = '名前は40文字以内で入力してください';
        } else {
            $name = $_POST['name'];
        }
        //コメントのチェック
        $comment = null;
        //名前がnull出ないことをチェック
        if(!isset($_POST['comment']) || !strlen($_POST['comment'])) {
            $errors['comment'] = 'コメントを入力してください';
        } else if (strlen($_POST['comment']) > 200) {
            $errors['comment'] = 'コメントは200文字以内で入力してください';
        } else {
            $comment = $_POST['comment'];
        }
        //エラーがなければ保存
        if (count($errors) === 0) {
            //保存するためのSQL分を作成
            $sql ='INSERT INTO post(pname, comment, created_day)VALUES("'
                .mysqli_real_escape_string($mysql, $name).'","'
                .mysqli_real_escape_string($mysql, $comment).'",\''
                .date('Y-m-d H:i:s').'\')';
            //保存する
            mysqli_query($mysql, $sql);
            //接続を閉じる
            mysqli_close($mysql);
            header('location: http://' .$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
        }
    }
    include 'views/bbs_view.php';
?>


//bbs_view.php

<?php
    //投稿された内容を取得し、SQLで結果取得
    $sql = "SELECT * FROM `post` ORDER BY `created_day` DESC";
    $result = mysqli_query($mysql, $sql);
    
    //取得結果を$postsに格納
    $posts = array();
    if ($result != false && mysqli_num_rows($result)) {
        while ($post = mysqli_fetch_assoc($result)) {
            $posts[] = $post;
        }
    }
    //取得結果の解放と接続を閉じる
    mysqli_free_result($result);
    mysqli_close($mysql);
    ?>
<?php
	mysqli_free_result($result);
	mysqli_close($mysql);
?>
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="views/bbs.css">
        <title>BBS</title>
    </head>
    <body>
        <h1>BBS</h1>
        <form action="bbs.php" method="post">
            <!-- エラーがあれば表示 -->
            <?php if (count($errors)): ?>
            <ul class="error_list">
                <?php foreach ($errors as $error): ?>
                <li>
                    <?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8') ?>
                </li>
                <?php endforeach; ?>
            </ul>
            <?php endif; ?>
            名前: <input type="text" name="name" /><br>
            内容: <input type="text" name="comment" size="60" /><br>
            <input type="submit" name="submit" value="送信" />
        </form>
        <!-- 取得内容を表示 -->
        <?php if (count($posts) > 0): ?>
        <ul>
            <?php foreach ($posts as $post): ?>
            <li>
                <?php echo htmlspecialchars($post['pname'], ENT_QUOTES, 'UTF-8'); ?>
                <?php echo htmlspecialchars($post['comment'], ENT_QUOTES, 'UTF-8'); ?>
                - <?php echo htmlspecialchars($post['created_day'], ENT_QUOTES, 'UTF-8'); ?>
            </li>
            <?php endforeach; ?>
        </ul>
        <?php endif; ?>
    </body>
</html>

クライアント側の処理とサーバー側の処理を分けることで、可読性も上がりました。
bbs.phpの最後に “include 読み込み対象ファイル”を入れることで、bbs_view.phpが読み込まれ、画面表示
される仕組みとなっています。
cssファイルに関しては、次章で説明するので、次章の最後に完成コードを記載します。

見栄え改善

今回で一旦簡易掲示板は完成ということになるので、機能的には想定していたものをすべて盛り込めたのですが、
見た目が何とも不細工な感じですよね。
この辺り少しでも改善できたらと思い、コード書いてみました。
まず最初に改善した部分が、エラーメッセージおよび投稿内容の表示に関してです。
エラーメッセージももちろんですが、投稿内容もあまり目を引けないデザインなので、少しきれいにしてみました。

ul {
	padding: 0.5em;
	list-style-type: none;
}
ul li {
	position: relative;
	padding: 0.5em 1em 0.5em 2.3em;
	margin-bottom:5px;
}
ul li:after,
ul li:before{
	content:'';
	position: absolute;
	border-radius: 50%;
}
ul li:before {
	top: 50%;
	left: 0.2em;
	width: 17px;
	height: 17px;
	background: rgba(25,118,210, 1);
	transform: translateY(-50%);
}
ul li:after {
	top: 1.1em;
	left: 0.7em;
	width: 14px;
	height: 14px;
	background: rgba(25,118,210, 0.5);
}

cssに関しては、今回は深く触れませんが、いろんなデザインを試すことが出来るので、皆さんの好きな雰囲気にしてもらえればと思います。

少しさわやかな印象を表現できたのではないでしょうか。
個人的に左のアイコンが気に入っています。
ネットで検索すると、おしゃれなデザインのソースがあったりするので、そちらを参考にしてみても
いいかもしれません。

//bbs.css

ul {
	padding: 0.5em;
	list-style-type: none;
}
ul li {
	position: relative;
	padding: 0.5em 1em 0.5em 2.3em;
	margin-bottom:5px;
}
ul li:after,
ul li:before{
	content:'';
	position: absolute;
	border-radius: 50%;
}
ul li:before {
	top: 50%;
	left: 0.2em;
	width: 17px;
	height: 17px;
	background: rgba(25,118,210, 1);
	transform: translateY(-50%);
}
ul li:after {
	top: 1.1em;
	left: 0.7em;
	width: 14px;
	height: 14px;
	background: rgba(25,118,210, 0.5);
}
input[type='text']{
    width: 100%;
    max-width: 400px;
    margin-left:5px;
    margin-top:10px;
    padding: 5px;
    border-radius: 5px;
    border: 1px solid #ccc;
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
}
input[type='submit']{
    margin-top:10px;
    margin-left:60px;
    display       : inline-block;
    border-radius : 5%;          /* 角丸       */
    font-size     : 13pt;        /* 文字サイズ */
    text-align    : center;      /* 文字位置   */
    cursor        : pointer;     /* カーソル   */
    padding       : 11px 12px;   /* 余白       */
    background    : #cccccc;     /* 背景色     */
    color         : #000000;     /* 文字色     */
    line-height   : 1em;         /* 1行の高さ  */
    opacity       : 1;           /* 透明度     */
    transition    : .3s;         /* なめらか変化 */
}
input[type='submit']:hover{
    box-shadow    : none;        /* カーソル時の影消去 */
    opacity       : 0.8;         /* カーソル時透明度 */
}

フォームの入力分と送信ボタンもデフォルトのままだと不細工なので、cssで調整しました。
送信ボタンに関しては、下記のサイトで簡単にデザイン調整が出来るので、参考までに
紹介します。

https://webparts.cman.jp/button/submit/

全体のデザイン及び、少し掲示板風に投稿してみたものを下記画像で紹介します。

デザイン回りもすこしきれいにできたかと思います。
投稿に関しても、問題なく反映されていて、簡易掲示板は一旦作成完了となります。

終わりに

本記事で簡易掲示板の作成は終了します。次回以降はよりSNSに近づけるために、機能面等こだわっていきたいと思います。
フレームワークなども駆使して、次回以降製造していきたいと思います。
次回記事では、まずログイン画面から作っていきたいと思います。