MySQL データベースに読み/書き/更新/削除できる WEBアプリ のコードサンプルです
前提(準備できていること)
バックエンドアプリ[app.js]が実行されていて、ポート3000などで待ち受けされていることが前提です。
$ node app.js
Node.js is listening to PORT: 3000
ここからフロントWEBアプリを開発します
HTMLファイル[index.html]
下記タグが含まれていることを確認します。HTMLファイルは、Apache2サーバーのディレクトリに保存します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>フロントWEBアプリ</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script type="text/javascript" src="crud.js"></script>
</head>
<body style="background-color:lightblue;">
<h1>フロントWEBアプリ</h1>
<button onclick="getName()">データを取得</button>
<div id="server"></div>
<div id="output"></div>
</body>
</html>
JavaScriptファイル[crud.js]
HTMLを表示したら最初に実行されるコード
// -------------------------------
// 初期設定
// -------------------------------
let server = "http://razpi00.local:3000";
// -------------------------------
// HTMLを全て読み込んだ後で、自動実行するスクリプト
// -------------------------------
window.onload = function start() {
document.getElementById('server').innerHTML = '<p>' + server + '</p>';
}
ブラウザでアクセス検査
ブラウザでアクセスして、HTMLを表示できることを確認します。下図の画面が表示されたら次に進みます。
CORS に注意!
CORS とは、プログラムが違うサーバーのプログラムにアクセスするときのセキュリティの仕組みです。
- フロントWEBアプリのサーバーは http://razpi00.local/ であり、実際にはポート80で動いています
つまり http://razpi00.local:80/ と同じサーバーを指しています - バックエンドアプリのサーバーは http://razpi00.local:3000/ であり、ポート3000で動いています
同じラズパイ1台の中で、サーバーは2個動いています。この場合、CORSでアクセス許可しないと、エラーが発生して[データを取得]ボタンが機能しません。下記のCORSで許可するコードを、バックエンドアプリ[app.js]の初期設定の後に追加してください(var app=express()より後の行です)。
// CORSで許可する
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
next();
});
このコードは、全てのサーバー(‘*’)からのアクセス(Get, Post, Put, Delete)を許可(Authorizaiton)するという意味です。このコードが無いときは、別のサーバーからのアクセスはブロック(拒否)されます。
CORSエラーの例
バックエンドサーバーが全てのアクセスを許可したら、フロントWEBアプリ側も正しいことを確認する
データを読む getName() コードを追加[crud.js]
[データを取得]ボタンを押したら、バックエンドサーバーを経由して MySQL データベースからデータを読み込みます。
// -------------------------------
// 初期設定
// -------------------------------
let server = "http://razpi00.local:3000";
// -------------------------------
// HTMLを全て読み込んだ後で、自動実行するスクリプト
// -------------------------------
window.onload = function start() {
document.getElementById('server').innerHTML = '<p>' + server + '</p>';
}
// ----------------------------------------------
// データベースからデータを読み込む。
// 読み込んだ結果をHTMLの <div id='output'></div> の場所に表示する
// ----------------------------------------------
async function getName() {
// バックエンドサーバーの getアプリ を実行する
// ここで getアプリ から回答があるまで待つ[await]。回答は response に代入
const response = await fetch(server + '/get', {mode:'cors'});
// 読み込んだデータを人が読みやすい json 形式に変換して HTMLの'output'の場所に表示する
const text = await response.text();
document.getElementById('output').innerHTML = '<p>' + text +'</p>';
}
ブラウザでアクセス検査
[データを取得]ボタンを押して、json形式のデータが表示されたら合格です。
ステップアップ1.テキストだけ表示する
少し読みやすくしましょう。getName()コードを改造します。
async function getName() {
// バックエンドサーバーの getアプリ を実行する
// ここで getアプリ から回答があるまで待つ[await]。回答は response に代入
const response = await fetch(server + '/get', {mode:'cors'});
// 読み込んだデータを人が読みやすい json 形式に変換して HTMLの'output'の場所に表示する
//★削除★ const text = await response.text();
//★削除★ document.getElementById('output').innerHTML = '<p>' + text +'</p>';
const jsonObj = await response.json();
let html = '';
jsonObj.forEach(item => {
html += `<p>ID: ${item.userid}, Name: ${item.passwd}, Data: ${item.email}</p>`;
});
document.getElementById('output').innerHTML = html;
}
ブラウザで検査する
ステップアップ2.表にする
もっと読みやすくしましょう。getName()コードをさらに改造します。
async function getName() {
// バックエンドサーバーの getアプリ を実行する
// ここで getアプリ から回答があるまで待つ[await]。回答は response に代入
const response = await fetch(server + '/get', {mode:'cors'});
// 読み込んだデータを人が読みやすい json 形式に変換してから HTMLの'output'の場所に表形式で表示する
const jsonObj = await response.json();
let html = '<table border="1"><tr><th>ID</th><th>Name</th><th>Data</th></tr>';
jsonObj.forEach(item => {
html += `<tr><td>${item.userid}</td><td>${item.passwd}</td><td>${item.email}</td></tr>`;
});
html += '</table>';
document.getElementById('output').innerHTML = html;
}
ブラウザで検査する
表ができたら完成です。おつかれさまでした!
データを書き込み
// データベースにデータを書き込む
async function putName() {
var name = document.getElementById('inputName').value;
var data = document.getElementById('inputData').value;
if (name == '' || data == '') {
document.getElementById('output').innerHTML = '<p>名前とデータが不足しています<i class="fa-solid fa-pen"></i></p>';
return;
}
try {
document.getElementById('output').innerHTML = '<p>書き込みしています</p><i class="fa fa-cog fa-spin fa-3x fa-fw"></i>';
const response = await fetch(server + `/put_name?name=${encodeURIComponent(name)}&data=${encodeURIComponent(data)}`);
if (!response.ok) {
throw new Error('(putName) APIサーバーに届きません。ネットワークの応答が正しくありません');
}
let html = "名前[" + name + "]とデータ[" + data + "]を書き込みました";
document.getElementById('output').innerHTML = html;
} catch (error) {
document.getElementById('output').innerHTML = '<p>エラーが発生しました<br />' + error +'</p>';
console.error('(putName) Error:', error);
}
}
データを削除する
// データを削除する
async function deleteName() {
var targetID = document.getElementById('inputID').value;
if (targetID == '') {
document.getElementById('output').innerHTML = '<p>削除するIDが不足しています<i class="fa-solid fa-pen"></i></p>';
return;
}
try {
document.getElementById('output').innerHTML = '<p>削除しています</p><i class="fa fa-cog fa-spin fa-3x fa-fw"></i>';
const response = await fetch(server + `/delete_name?id=${targetID}`);
if (!response.ok) {
throw new Error('(deleteName) APIサーバーに届きません。ネットワークの応答が正しくありません');
}
let html = "ID[" + targetID + "]を削除しました";
document.getElementById('output').innerHTML = html;
} catch (error) {
document.getElementById('output').innerHTML = '<p>エラーが発生しました<br />' + error +'</p>';
console.error('(deleteName) Error:', error);
}
}
データを更新する
// データベースを更新する
async function updateName() {
var targetID = document.getElementById('inputID').value;
var name = document.getElementById('inputName').value;
var data = document.getElementById('inputData').value;
try {
document.getElementById('output').innerHTML = '<p>データを変更しています<i class="fa fa-cog fa-spin fa-3x fa-fw"></i></p>';
const response = await fetch(server + `/update_name?id=${targetID}&name=${encodeURIComponent(name)}&data=${encodeURIComponent(data)}`);
if (!response.ok) {
throw new Error('(putName) APIサーバーに届きません。ネットワークの応答が正しくありません');
}
let html = "名前[" + name + "]とデータ[" + data + "]を書き込みました";
document.getElementById('output').innerHTML = html;
} catch (error) {
document.getElementById('output').innerHTML = '<p>エラーが発生しました<br />' + error +'</p>';
console.error('(putName) Error:', error);
}
}
機能メニュー(HTML)
</head>
<body>
<h1>API操作サンプル</h1>
<p>サーバー:</p><div id="server"></div>
<p>ID:<input type="text" id="inputID" placeholder="削除するID番号を入力してください"></p>
<p>名前:<input type="text" id="inputName" placeholder="追加するデータ名を入力してください"></p>
<p>データ:<input type="text" id="inputData" placeholder="データを入力してください"></p>
<button onclick="putName()">データを追加</button>
<button onclick="getName()">データを取得</button>
<button onclick="deleteName()">データを削除</button>
<button onclick="updateName()">データを更新</button>
<div id="output"></div>
</body>
</html>