Skip to content

ユーザー情報を投稿に紐付けてみよう

osamu38 edited this page Mar 8, 2016 · 21 revisions

ユーザー情報を投稿に紐付けてみよう

目次

  • ボードにユーザーを紐付けよう
  • メッセージにユーザーを紐付けよう
  • 部品を共通化しよう

ボードにユーザーを紐付けよう

routes/index.jsを以下のように書き換えます。

  // 中略
  var title = req.body.title;
  var userId = req.session.user_id? req.session.user_id: 0; // 追加
  var createdAt = moment().format('YYYY-MM-DD HH:mm:ss');
  var query = 'INSERT INTO boards (user_id, title, created_at) VALUES ("' + userId + '", ' + '"' + title + '", ' + '"' + createdAt + '")'; // 変更
  connection.query(query, function(err, rows) {
  // 中略

ログインしているユーザーはsessionにユーザーIDを保持しているため、req.session.user_idで取得できます。ログインしていない場合は0を代入しています。

ではさっそくログインしている状態で投稿してみましょう。

4回目の投稿のuser_id1がセットされていますね。これでボードにユーザーIDを紐付けられました。

ではこのuser_idをもとにユーザ名を取得し、ボードにユーザー名を表示させましょう。

routes/index.jsを以下のように書き換えます。

// 中略
router.get('/', function(req, res) {
  var query = 'SELECT B.board_id, B.user_id, B.title, ifnull(U.user_name, \'名無し\') AS user_name, DATE_FORMAT(B.created_at, \'%Y年%m月%d日 %k時%i分%s秒\') AS created_at FROM boards B LEFT OUTER JOIN users U ON B.user_id = U.user_id ORDER BY B.created_at DESC'; // 変更
  connection.query(query, function(err, rows) {
  // 中略

少し長いクエリーになってしまいましたが、ここでは2つのテーブル(boardsusers)をuser_idをもとに紐付ける処理を記述してあります。

またログインされていない状態での投稿はuser_id0になるため、紐付けられるユーザーアカウントは存在しません。そのためuser_namenullになってしまうので、MySQLのifnullを使って、nullの場合は「名無し」に変更するような処理をしています。

これでユーザー名が取得できたのでViewファイルで変更しましょう。

views/index.ejsを以下のように書き換えます。

                    <!-- 中略 -->
                    <p class="board__title"><%= boardItem.title %></p>
                    <p class="board__date"><%= boardItem.user_name %> <%= boardItem.created_at %></p><!-- 変更 --> 
                </a>
         <!-- 中略 -->

この状態で/にアクセスすると...

ボード作成者の名前が表示されているのがわかりますね。

メッセージにユーザーを紐付けよう

では次にメッセージにユーザーIDを紐付けてみましょう。この処理はボードにユーザーIDを紐付ける作業とほぼ同じなのである程度説明は省きます。

views/board.ejsを以下のように書き換えます。

                          <!-- 中略 -->
                          <p class="message__title"><%= messageItem.message %></p>
                          <p class="message__date"><%= messageItem.user_name %> <%= messageItem.created_at %></p><!-- 変更 -->
                      </div>
                      <!-- 中略 -->

routes/boards.jsを以下のように書き換えます。

  // 中略
  var getBoardQuery = 'SELECT * FROM boards WHERE board_id = ' + boardId;
  var getMessagesQuery = 'SELECT M.message, ifnull(U.user_name, \'名無し\') AS user_name, DATE_FORMAT(M.created_at, \'%Y年%m月%d日 %k時%i分%s秒\') AS created_at FROM messages M LEFT OUTER JOIN users U ON M.user_id = U.user_id WHERE M.board_id = ' + boardId + ' ORDER BY M.created_at ASC'; // 変更
  connection.query(getBoardQuery, function(err, board) {
  // 中略



  // 中略
  var boardId = req.params.board_id;
  var userId = req.session.user_id? req.session.user_id: 0; // 追加
  var createdAt = moment().format('YYYY-MM-DD HH:mm:ss');
  var query = 'INSERT INTO messages (message, board_id, user_id, created_at) VALUES ("' + message + '", ' + '"' + boardId + '", ' + '"' + userId + '", ' + '"' + createdAt + '")'; // 変更
  connection.query(query, function(err, rows) {
  // 中略

views/board.ejsroutes/boards.jsの対応をしたのでさっそくアクセスしてみましょう!

データの挿入と表示がされているのがわかりますね。これでボードとメッセージにユーザー情報を紐付けることができました。

部品を共通化しよう

ここまで作ったらあとは会員登録やログインなどのページへのリンクを設定します。ですがviews/index.ejsviews/board.ejs、また違うページのすべてにリンクを設定するのは非常に手間がかかります。

なのでそういった部品を共通化するためのモジュール、ejs-localsを導入してみましょう。

$ npm install ejs-locals --save

app.jsを以下のように書き換えます。

var express = require('express');
var engine = require('ejs-locals'); // 追加
var path = require('path');
// 中略



// 中略
// view engine setup
app.engine('ejs', engine); // 追加
app.set('views', path.join(__dirname, 'views'));
// 中略

ここではejs-localsを使えるようにapp.jsに設定を行っています。では共通部品をまとめてみましょう。

views/layout.ejsを作成します。

<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="format-detection" content="telephone=no">
<link rel='stylesheet' href='/stylesheets/style.css'>
</head>
<body>
<div class="wrapper">
    <%- body %>
    <% if (typeof user !== 'undefined') { %>
        <a href="/logout" class="btn">ログアウト</a>
    <% } else { %>
        <a href="/register" class="btn">会員登録</a>
        <a href="/login" class="btn">ログイン</a>
    <% } %>
</div>
</body>
</html>

views/layout.ejsは全ページ共通で使う部品を別ファイルとして作成したもので、<%- body %>の中に各Viewファイルの中身が入ってきます。

    <% if (typeof user !== 'undefined') { %>
        <a href="/logout" class="btn">ログアウト</a>
    <% } else { %>
        <a href="/register" class="btn">会員登録</a>
        <a href="/login" class="btn">ログイン</a>
    <% } %>

userが存在する場合(ログイン状態)ではログアウトが表示されるようにし、userが存在しない場合(非ログイン状態)では会員登録とログインを表示されるように条件分岐しています。

それに伴って作ったejsファイルを一通り変更します。

views/index.ejsを以下のように書き換えます。

    <% layout('layout') %>
    <form action="/" method="post" class="board-form">
        タイトル: <input type="text" name="title" class="input" required><br>
        <br>
        <button type="submit" class="submit">ボード作成</button>
    </form>
    <ul class="main-list">
        <% boardList.forEach(function(boardItem) { %>
            <li class="main-list__item">
                <a href="/boards/<%= boardItem.board_id %>" class="board">
                    <p class="board__title"><%= boardItem.title %></p>
                    <p class="board__date"><%= boardItem.user_name %> <%= boardItem.created_at %></p>
                </a>
            </li>
        <% }); %>
    </ul>
    <% if (typeof user !== 'undefined') { %>
        <span class="login-user"><%= user.user_name %>さんとしてログインしています</span>
    <% } %>

views/board.ejsを以下のように書き換えます。

    <% layout('layout') %>
    <p class="main-title"><%= title %></p>
    <% if (messageList.length) { %>
      <div class="white-bg">
          <ul class="main-list">
              <% messageList.forEach(function(messageItem) { %>
                  <li class="main-list__item">
                      <div class="message">
                          <p class="message__title"><%= messageItem.message %></p>
                          <p class="message__date"><%= messageItem.user_name %> <%= messageItem.created_at %></p>
                      </div>
                  </li>
              <% }); %>
          </ul>
      </div>
    <% } %>
    <form action="/boards/<%= board.board_id %>" method="post" class="board-form">
        <input type="text" name="message" class="input" required>
        <button type="submit" class="submit">投稿</button>
    </form>
    <% if (typeof user !== 'undefined') { %>
        <span class="login-user"><%= user.user_name %>さんとしてログインしています</span>
    <% } %>
    <a href="/" class="btn">トップへもどる</a>

views/register.ejsを以下のように書き換えます。

    <% layout('layout') %>
    <p class="main-title"><%= title %></p>
    <form action="/register" method="post" class="board-form">
        <span class="label">ユーザー名</span><input type="text" name="user_name" class="input" required><br>
        <br>
        <span class="label">Eメール</span><input type="email" name="email" class="input" required><br>
        <br>
        <span class="label">パスワード</span><input type="password" name="password" class="input" required><br>
        <br>
        <button type="submit" class="submit">新規会員登録</button>
    </form>
    <% if (typeof emailExists !== 'undefined') { %>
        <p class="error"><%= emailExists %></p>
    <% } %>
    <a href="/" class="btn">トップへもどる</a>

views/login.ejsを以下のように書き換えます。

    <% layout('layout') %>
    <p class="main-title"><%= title %></p>
    <form action="/login" method="post" class="board-form">
        <span class="label">Eメール</span><input type="email" name="email" class="input" required><br>
        <br>
        <span class="label">パスワード</span><input type="password" name="password" class="input" required><br>
        <br>
        <button type="submit" class="submit">ログイン</button>
    </form>
    <% if (typeof noUser !== 'undefined') { %>
        <p class="error"><%= noUser %></p>
    <% } %>
    <a href="/" class="btn">トップへもどる</a>

ソースコードがとてもさっぱりしましたね。このようにejs-localsのlayout機能を使うことで共通部品をまとめることができました。

前のページ:Node.jsで会員登録システムを導入しよう

次のページ:画像を投稿してみよう