ユーザー情報を投稿に紐付けてみよう - osamu38/node-express-curriculum GitHub Wiki
- ボードにユーザーを紐付けよう
- メッセージにユーザーを紐付けよう
- 部品を共通化しよう
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_id
に1
がセットされていますね。これでボードにユーザー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つのテーブル(boards
とusers
)をuser_id
をもとに紐付ける処理を記述してあります。
またログインされていない状態での投稿はuser_id
が0
になるため、紐付けられるユーザーアカウントは存在しません。そのためuser_name
がnull
になってしまうので、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.ejs
とroutes/boards.js
の対応をしたのでさっそくアクセスしてみましょう!
データの挿入と表示がされているのがわかりますね。これでボードとメッセージにユーザー情報を紐付けることができました。
ここまで作ったらあとは会員登録やログインなどのページへのリンクを設定します。ですがviews/index.ejs
やviews/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で会員登録システムを導入しよう
次のページ:画像を投稿してみよう