Expressで基本的なCRUDアプリを作成する際の手順をまとめました。
DBにはMySQLを使います。
対象読者
初めてExpressを触る方
使用したバージョン
macOS Catalina 10.15.4
node:v12.14.0
MySQL:v8.0.19
Express:v4.17.1
MySQLを使う準備
自前のMacにMySQLが入っていない場合、MySQLをhomebrew経由でインストールする。
brew install mysql
// 起動
mysql.server start
// 停止
mysql.server stop
//ステータス確認
mysql.server status
// バージョン確認
mysqld --version
*MySQLのバージョンが8以上の場合、node.jsからMySQLへの接続時エラーが出るため以下のページを参考にすると良いです。
[Express.js(node.js)からMySQLへの接続とCRUD操作 | アールエフェクト] (https://reffect.co.jp/node-js/express-js-connect-mysql#MySQL)
プロジェクト作成〜Hello Worldまで
適当なディレクトリを作ってnpm init -y
でプロジェクトを作成。
npm install express
でexpressインストール
npm install mysql
でmysqlインストール
npm install ejs
でejsインストール
###DB作成
create-database.jsを作成し、以下を記述します。
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',//mysqlと合わせる
password: '',//mysqlと合わせる
});
//mysqlに接続してデータベース作成(成功するとconsoleに'database created'と出る)
connection.connect(function(err) {
if (err) throw err;
console.log('Connected');
connection.query('CREATE DATABASE express_db', function (err, result) {
if (err) throw err;
console.log('database created');
});
});
※mysqlはmysql.server start
のコマンドで立ち上げておきます。
node create-database.js
を実行するとDBが作成されます。
###テーブル作成
create-table.jsを作成し、以下を記述します。
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',//mysqlと合わせる
password: '',//mysqlと合わせる
database: 'express_db' //先ほど作成したDBの名前
});
//テーブルの作成
connection.connect(function(err) {
if (err) throw err;
console.log('Connected');
const sql = 'CREATE TABLE items (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255) NOT NULL, text VARCHAR(255) NOT NULL)';
connection.query(sql, function (err, result) {
if (err) throw err;
console.log('table created');
});
});
node create-table.js
を実行するとitemsテーブルが作成されます。
###ローカルサーバーの設定
app.jsを作成し、以下を記述します。
const express = require('express');
const mysql = require('mysql');
const app = express();
app.use(express.static('public'));//静的配信のフォルダを指定
app.use(express.urlencoded({extended: false}));
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',//mysqlと合わせる
password: '',//mysqlと合わせる
database: 'express_db' //先ほど作成したDBの名前
});
//viewsディレクトリ以下のejsファイル認識させる
app.set('views', './views');
app.set('view engine', 'ejs');
//hello world
app.get("/", (req,res) => {
res.send("Hello World");
});
app.listen(3000);//3000ポートでローカルサーバーたつ
node app.js
を実行するとローカルでサーバが立ちます。
localhost:3000にアクセスすると'Hello World'と表示されます。
CRUD
app.jsを編集し、基本的なCRUD機能を実装していきます。
※変更を加えた際は、ブラウザで確認する前に一度ctrl+Cでサーバーを停止させてから再度node app.js
を実行してください。
作成(create)
const express = require('express');
const mysql = require('mysql');
const app = express();
app.use(express.static('public'));
app.use(express.urlencoded({extended: false}));
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'express_db'
});
//viewsディレクトリ以下のejsファイル認識させる
app.set('views', './views');
app.set('view engine', 'ejs');
//hello-world
app.get("/", (req,res) => {
res.send("Hello World");
});
/* ============ここから追加============ */
//新規作成画面のルーティング
app.get('/new', (req, res) => {
res.render('new.ejs');
});
//新規作成アクション
app.post('/create', (req, res) => {
connection.query(
'INSERT INTO items (title, text) VALUES (?, ?)',
[req.body.itemTitle, req.body.itemText],
(error, results) => {
res.redirect('/')//methodがpostのときはredirectを使う
}
);
});
/* ============ここまで追加============ */
app.listen(3000);
<form action="/create" method="post">
<input type="text" name="itemTitle">
<input type="text" name="itemText">
<input type="submit" value="作成する">
</form>
localhost:3000/newにアクセスすると、フォームが表示されるようになります。
「作成する」をクリックすると、DBにデータが保存されます。
一覧(read)
Hello Worldと表示させていた部分を投稿したデータが一覧表示されるようにします。app.jsを修正し、index.ejsを新規作成します。
const express = require('express');
const mysql = require('mysql');
const app = express();
app.use(express.static('public'));
app.use(express.urlencoded({extended: false}));
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'express_db'
});
//viewsディレクトリ以下のejsファイル認識させる
app.set('views', './views');
app.set('view engine', 'ejs');
/* ============ここから変更============ */
//一覧画面のルーティング
app.get('/', (req, res) => {
connection.query(
'SELECT * FROM items',
(error, results) => {
res.render('index.ejs', {items: results});//itemというキーでviewにデータベースの中身を渡せる
}
);
});
/* ============ここまで変更============ */
//新規作成画面のルーティング
app.get('/new', (req, res) => {
res.render('new.ejs');
});
//新規作成アクション
app.post('/create', (req, res) => {
connection.query(
'INSERT INTO items (title, text) VALUES (?, ?)',
[req.body.itemTitle, req.body.itemText],
(error, results) => {
res.redirect('/')
});
});
app.listen(3000);
<% items.forEach((item) => { %>
<li>
<div>
<span><%= item.title %></span>
<span><%= item.text %></span>
</div>
</li>
<% }) %>
編集(update)
一覧画面から、それぞれの記事の編集画面に飛べるようにapp.jsとindex.ejsを修正し、edit.ejsを新規作成します。
/* ~~省略~~ */
//新規作成画面のルーティング
app.get('/new', (req, res) => {
res.render('new.ejs');
});
//新規作成アクション
app.post('/create', (req, res) => {
connection.query(
'INSERT INTO items (title, text) VALUES (?, ?)',
[req.body.itemTitle, req.body.itemText],
(error, results) => {
res.redirect('/')
});
});
/* ============ここから追加============ */
//編集画面へのルーティング
app.get('/edit/:id', (req, res) => {
connection.query(
'SELECT * FROM items WHERE id = ?',
[req.params.id],
(error, results) => {
res.render('edit.ejs', {item: results[0]});
}
);
});
//更新アクション
app.post('/update/:id', (req, res) => {
connection.query(
'UPDATE items SET title = ?, text = ? WHERE id = ?',[req.body.itemTitle, req.body.itemText, req.params.id],(error,results)=>{
res.redirect('/');
})
});
/* ============ここまで追加============ */
app.listen(3000);
<% items.forEach((item) => { %>
<li>
<div>
<span><%= item.title %></span>
<span><%= item.text %></span>
</div>
</li>
<!-- ============ここから追加============ -->
<a href="/edit/<%= item.id %>">編集</a>
<!-- ============ここまで追加============ -->
<% }) %>
<form action="/update/<%= item.id %>" method="post">
<input type="text" name="itemTitle" value="<%= item.title %>">
<input type="text" name="itemText" value="<%= item.text %>">
<input type="submit" value="更新する">
</form>
削除(delete)
一覧画面から、それぞれの記事を削除できるようにapp.jsとindex.ejsを修正します。
/* ~~省略~~ */
//編集画面へのルーティング
app.get('/edit/:id', (req, res) => {
connection.query(
'SELECT * FROM items WHERE id = ?',
[req.params.id],
(error, results) => {
res.render('edit.ejs', {item: results[0]});
}
);
});
//更新アクション
app.post('/update/:id', (req, res) => {
connection.query(
'UPDATE items SET title = ?, text = ? WHERE id = ?',[req.body.itemTitle, req.body.itemText, req.params.id],(error,results)=>{
res.redirect('/');
})
});
/* ============ここから追加============ */
//削除
app.post('/delete/:id', (req, res) => {
connection.query(
'DELETE FROM items WHERE id = ?',
[req.params.id],
(error, results) => {
res.redirect('/');
}
);
});
/* ============ここまで追加============ */
app.listen(3000);
<% items.forEach((item) => { %>
<li>
<div>
<span><%= item.title %></span>
<span><%= item.text %></span>
</div>
</li>
<a href="/edit/<%= item.id %>">編集</a>
<!-- ============ここから追加============ -->
<form action="/delete/<%= item.id %>" method="post">
<input type="submit" value="削除">
</form>
<!-- ============ここまで追加============ -->
<% }) %>
以上でCRUD機能の実装は完了です!
##完成形
GitHubに完成形のコードを上げてます。ご参考まで。
##参考
//mysqlのインストール(記事の前半部分)
https://reffect.co.jp/laravel/mysql-laravel-in-mac
//データベースの作成、テーブルの作成など
https://reffect.co.jp/node-js/express-js-connect-mysql