本記事ではNode.js
、Express
、SQLite
を使って、DataBaseにCRUDするアプリの開発工程を紹介をします。実際に作るのはシンプルなTo Doメモアプリなので初心者向けです。
掌田津耶乃さんのNode.js超入門がベースです。
一応念のため、CRUDとは
- Create(登録) 新しいデータを登録
- Read(参照) レコードをテーブルから取り出す
- Update(更新) レコードの内容を更新
- Delete(削除) レコードを削除
一応念のため、Webアプリケーションとは(サイトとの違い)
Webサイト=情報を提供
静的ファイルをホスティングしてるだけで、誰が見ても同じ情報を表示する。
Webアプリケーション=情報のやり取り
ユーザーがフォーム入力、送信、など様々な行動をアプリケーション上で行える。ユーザーが送信したデータを処理して結果を表示する。
実践
では実際にやっていきましょう。大きく分けて以下4ステップで進めていきます。
Step1: Node.jsアプリ基盤構築
Step2: DataBase構築
Step3: ページを用意
Step4: CRUD処理を実装
前提条件:Node.jsのインストール。インストールの仕方はこちらを参考
Step1: Node.jsアプリ基盤構築
入門編でも紹介したアプリケーションのひな形を生成してくれる便利なツールのExpress-Generator
をインストールしましょう。
npm install -g express-generator
これでグローバルにインストールされてシステム全体でExpress-Generatorが使えます。
では以下のコマンドでアプリを作成します。 express -e アプリ名
express -e todo-app
これでtodo-app
という名前のディレクトリができ、各種フォルダも自動で作られます。
Express-Generatorはデフォルトで各種パッケージを入れておいてくれるので、プロジェクトディレクトリに入り、npm installをして全部インストールしましょう。
cd todo-app
npm install
そして、今回DataBaseを扱う為に必要なSQLite3
は、別途インストールが必要なので、以下のコマンドを打ちます。
npm install --save sqlite3
各ディレクトリの説明をざっくり
-
bin/
アプリを実行する為のコマンドとなるファイルが保管されてます。基本的に触りません。 -
public/
CSSや画像などをこの中に置きます。 -
routes/
このディレクトリではルート(URL)ごとの処理がまとめらています。
用意するページのアドレス単位で、ここにファイルを追加します。 -
views/
画面側を作る上で必要なViewファイルを置きます。サーバーサイドからこのファイルに対して値を渡すことが出来ます。 -
node_modules/
npm installするとパッケージ類はこのディレクトリに入ってきます。基本的に触りません。 -
app.js
これがメインプログラムです。Expressの設定周りを担っています。
これでアプリの基盤はひとまず完成です。Express-Generatorを使うとすごい楽です。
Step2: DataBase構築
続いてDataBaseの構築です。
1. DB Browser for SQLite
を導入。
*DB Browser for SQLiteはSQLiteのデータベースをGUIで管理することができるツールです。 導入方法はこちらを参考にしてください、簡単です。
2. DataBaseファイルを作る
「新しいデータベース」をクリックします。
ファイル名は「memo_data」として、保存先はtodo-appフォルダ直下です。これでmemo_data.db / memo_data.sqlite3
というファイルが作られます。
3. テーブルを作る
今回は超シンプルなメモアプリなので、メモを格納するテーブル(テーブル名:memos)を一つだけ用意ます。
4. カラムを作る
カラムは以下2点に留めておきます。
- id: これは編集、削除する際にデータを特定する為に必須
- text
*もっとあってもいいですが今回はミニマムな実装に留めます。
最初に何個かダミーデータを登録しておきましょう。
(余談)普通のアプリ開発では必要なデータを洗い出して、テーブル、カラムをどう分けるかなどをこんな風に図に起こして 設計 するのが当たり前ですが、今回はシンプルなメモアプリなので設計なんて大そうな作業は不要です。
ちなみにテーブル、カラムなど超基本のデータベース用語ですが、
-
カラム
が列 -
レコード
が行 -
テーブル
がそれを全てまとめる表
のイメージです
データベース構築はこれで完了です。
Step3:ページを用意
続いてクライアント側の画面であるページを作っていきます。
Node.jsではテンプレートエンジン
というクライアント側の画面が簡単に作成できるパッケージがあります。Express-Generatorで既にejs
というテンプレートエンジンがインストール済みなので、これを使ってページを作っていきます。
今回必要なページは4つです。views配下にmemo
という名前でフォルダを作り、以下のファイルを作成してください。
- メモ一覧表示ページ: index.ejs
- 新規メモ追加ページ: add.ejs
- メモ編集ページ: edit.ejs
- メモ削除ページ: delete.ejs
各ファイルのコードは以下になります。
index.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h3><%= title %> <a href="/memo/add">追加</a></h3>
<div>
<table>
<% for(var i in content) { %>
<tr>
<% var obj = content[i]; %>
<td><%= obj.text %></td>
<td><a href="/memo/edit?id=<%= obj.id %>">更新</a></td>
<td><a href="/memo/delete?id=<%= obj.id %>">削除</a></td>
</tr>
<% } %>
</table>
</div>
</body>
</html>
add.ejs(index.ejsとbodyタグ以外は同じ)
<body>
<h3><%= title %></h3>
<p><%= content %></p>
<div>
<form action="/memo/add" method="post">
<p>メモ内容:<input type="text" name="text"></p>
<input type="submit" value="追加">
</form>
</div>
</body>
edit.ejs(index.ejsとbodyタグ以外は同じ)
<body>
<h3><%= title %></h3>
<p><%= content %></p>
<div>
<form action="/memo/edit" method="post">
<p>メモ内容:<input type="text" name="text" value="<%= memoData.text %>"></p>
<input type="hidden" name="id" value="<%= memoData.id %>">
<p><input type="submit" value="更新"></p>
</form>
</div>
</body>
delete.ejs(index.ejsとbodyタグ以外は同じ)
<body>
<h3><%= title %></h3>
<p><%= content %></p>
<div>
<p>メモ内容:<%= memoData.text %></p>
<form action="/memo/delete" method="post">
<input type="hidden" name="id" value="<%= memoData.id %>">
<p><input type="submit" value="削除"></p>
</form>
</div>
</body>
見ての通り基本はHTMLファイルで、値を受け取ってそれを表示したり、値を送ったりしているだけです。
title, content, memoData
という名前で値を送る処理はroutes(サーバー側)から行ってます。
Step4:CRUD処理を実装
最後に肝心のCRUD処理を実装していきます。
routes配下にmemo.js
というファイルを作り、以下の処理を書いていきます。
各所にコメントを入れてあります。
var express = require('express');
var router = express.Router();
var sqlite3 = require('sqlite3');
//データベースオブジェクトの取得
const db = new sqlite3.Database('memo_data.sqlite3');
router.get('/', function(req, res, next) {
db.serialize(() => {
//SQL文, memosテーブルから全てのレコードを取得する(* は全て)
db.all("select * from memos", (err, rows) => {
if (!err) {
const data = {
title: 'To Do メモ 一覧表示',
content: rows //DataBaseから返された全レコードがrowsに配列で入ります
}
//viewファイルのmemo/indexにdataオブジェクトが渡されます
//res.render(テンプレートファイル名, { 渡す値をオブジェクトで }) → テンプレートファイルを描画する
res.render('memo/index', data);
}
})
})
});
router.get('/add', function(req, res, next) {
const data = {
title: '追加',
content: '新しいデータを入力してください'
}
res.render('memo/add', data);
});
router.post('/add', function(req, res, next) {
const tx = req.body.text;
//SQL文, DataBaseのレコード作成
db.run('insert into memos (text) values (?)', tx)
//res.redirect() 引数に指定したアドレスにリダイレクト
res.redirect('/memo');
});
router.get('/edit', function(req, res, next) {
const id = req.query.id;
db.serialize(() => {
const q = "select * from memos where id = ?";
db.get(q, [id], (err, row) => {
if (!err) {
const data = {
title: '更新',
content: 'id = ' + id + 'のレコードを更新',
memoData: row
}
res.render('memo/edit', data);
}
})
})
});
router.post('/edit', function(req, res, next) {
//POST送信された値はreq.body内にまとまられている
const id = req.body.id;
const tx = req.body.text;
const q = "update memos set text = ? where id = ?";
db.run(q, tx, id);
res.redirect('/memo');
});
router.get('/delete', function(req, res, next) {
const id = req.query.id;
db.serialize(() => {
const q = "select * from memos where id = ?";
db.get(q, [id], (err, row) => {
if (!err) {
const data = {
title: '削除',
content: 'id = ' + id + 'のメモを削除しますか?',
memoData: row
}
res.render('memo/delete', data);
}
})
})
});
router.post('/delete', function(req, res, next) {
const id = req.body.id;
const q = "delete from memos where id = ?";
db.run(q, id);
res.redirect('/memo');
});
module.exports = router;
そして、app.js
に以下を追記してください
var memoRouter = require('./routes/memo');
app.use('/memo', memoRouter);
ここまでできたらnpm start
を実行して、http://localhost:3000/memo
を開いてください。
あらかじめ登録したダミーデータが表示されていれば一覧表示はうまくいってます。
追加、更新、削除も機能していればバッチリです。
なぜサーバーサイドアプリケーションが必要?
ローカルストレージ機能を使えば一時保存できるので、簡易的なメモアプリであればフロントだけで完結できます。
しかし、大きすぎるデータや、DataBaseにきちんと保存するのであればサーバーサイドで動くアプリケーションが必要になります。(ブラウザからDataBaseにアクセスできないから)
それ以外の理由ではフロント側でできない複雑な処理などをサーバーアプリ側でやってもらうと言う理由があります。
まとめ
テーブル1個のこんなシンプルなアプリなんて現場ではまずあり得ないですが、Node.js、サーバーサイドに入門には丁度いいと思います。
次はREST APIに関しての記事を書こうと思います。