9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MySQLで取得したデータを、EJSでWebブラウザに出力する

Last updated at Posted at 2021-01-17

はじめに

こちらは、エンジニアの新たな学びキャンペーンに向けた記事となります。

Node.js + Express で作る Webアプリケーション 実践講座を参考にしながら、
データベース(以下DB)内のデータを、Webブラウザに表示する方法を記事にしました。

なお、ここではNode.jsのテンプレートエンジンであるEJSと、RDB(リレーショナルデータベース)であるMariaDB(MySQL)を利用します。

(上記講座ではMongoDBが利用されていますが、本記事ではMySQLに置き換えました。)

実行環境

  • Node.js v12.16.3
  • Express 4.16.1
  • 10.4.11-MariaDB

対象者

  • JavaScriptの文法自体は学んだけど、Web技術はまだほとんど学べていない人
  • かんたんなCRUD操作に関するSQLを理解している人

本記事でわかること

  • サーバーサイド言語Node.js & フレームワークExpressを使い、Hello Worldする方法
  • ExpressとMariaDB(MySQL)の連携方法
  • ExpressとMariaDB(MySQL)を使い、DB内のデータをWebブラウザ上に出力する方法

対象のUdemy講座で学んだこと

対象の講座で学んだことのうち、特に本記事へ反映する内容は以下となります。

  • パッケージマネージャであるnpmを使い、ミドルウェアやフレームワークを導入する方法
  • EJSの構文の使い方
  • Expressでのルーティング方法(特に関数の引数に関して)

EJSとは

EJSは、テンプレートエンジンと呼ばれるもののひとつで、
テンプレートエンジンはHTMLの中にプログラム言語を埋め込むことができます。

特にEJSにおいては、HTML文書の中に<% %>, <%= %>タグなどを埋め込み、この中にプログラムを記述します。

EJSの基本構文

EJSの基本的な書き方にきれいにまとまっていたので、
こちらを参照すると幸せになれます。

EJSの利点

EJSは、サーバーサイドで保持している変数の値を併用してHTMLを記述するとき、書きやすさ・読みやすさの点で非常に強力です。

例えばサーバーサイド言語のみでHTML文書を書く場合、次のようなソースコードになります。

app.js
const express = require("express");
const app = express();

app.get("/", (req, res) => {
  const text = "Hello World";
  let data = "<!DOCTYPE html>\r\n";
  data += "<html>\r\n";
  data += "  <head>\r\n";
  data += "    <meta charset='UTF-8'>\r\n";
  data += "    <title>hoge</title>\r\n";
  data += "  </head>\r\n";
  data += "  <body>\r\n";
  data += "<p>";
  data += text
  data += "</p>\r\n";
  data += "  </body>\r\n";
  data += "</html>";
  res.send(data);
});
app.listen(3000);

一方で、テンプレートエンジンを併用した場合は、次のようになります。
クォーテーションや改行を意味する\r\nなどが消え、読み書きしやすくなっているのが分かります。

app.js
const express = require("express");
const app = express();
app.set("view engine", "ejs");

app.get("/", (req, res) => {
  const text = "Hello World";
  res.render("index", {text});
});
app.listen(3000);
index.ejs
<!DOCTYPE html>
<html>
  <head>
    <meta charset='UTF-8'>
    <title>hoge</title>
  </head>
  <body>
    <p><%= text %></p>
  </body>
</html>

実行の準備

さて、まずは環境の構築を行います。
Node.js, MariaDB(MySQL)はインストールされているものとします。

サーバーサイドの準備

以下のコマンドを順に実行して、フレームワークやミドルウェアを導入します。

  • $ npm init
  • $ npm install express --save,
  • $ npm install mysql
  • $ npm install ejs -- save

MariaDB(MySQL)の準備

以下のSQLを順に実行します。
この操作により、Webサイトの名前・URLに関するテーブルを作成し、データの追加も行います。

  • create database website
  • create table website(name varchar(255), url varchar(255));
  • insert into website(name, url) values ("google", "https://www.google.com/"), ("amazon", "https://www.amazon.co.jp/"), ("apple", "https://www.apple.com/"), ("facebook", "https://www.facebook.com/");

実装する

次のような順序で、簡単なことから実装していきます。

  1. EJSを使い、Webブラウザ上でHello Worldする
  2. DB接続を行いデータを取り出し、ターミナル上にデータを出力する
  3. DB接続を行い、EJSファイルを利用してWebブラウザ上にデータを出力する(ここでは一度失敗してみる)
  4. DB接続を行い、EJSファイルを利用してWebブラウザ上にデータを出力する(再チャレンジし、成功する)

1. EJSでHello Worldしてみよう

まずはDBのことは一旦 忘れて、EJSを使ってHello Worldをしてみます。

下記ソースコードを保存後、ターミナル上で$ node app.jsと入力し、
Webブラウザでhttp://localhost:3000/にアクセスします。

次の画像のように表示されたら成功です。
ちなみに、
app.jsのソースコード内のapp.get()の第一引数はリクエストURL、
第二引数はリクエストが送られたときに実行されるコールバック関数を指します。

この処理を口語的に説明するなら、
http://localhost:3000/が呼ばれたら次のコールバック関数を実行してね!
そしてそのコールバック関数には、index.ejsを表示して!っていう命令も含まれてるよ!
といったところでしょうか。

image.png

実行するソースコード

app.js
const express = require("express");
const app = express();
app.set("view engine", "ejs");

app.get("/", (req, res)=>{
    res.render("index.ejs");  // デフォルトでは /viewsからの相対パスで表すので注意
})

app.listen(3000);

views/index.ejs
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

2. DBに接続してみよう

次に、DB内のデータをターミナル上で表示する実装を行います。

app.jsを次のように書き換えます。
なお、mysql.createConnection()の各種ユーザ情報は、必要に応じて書きかえてください。

実行するソースコード

app.js
const express = require("express");
const app = express();
const mysql = require("mysql");
const connection = mysql.createConnection({
    host: "localhost",
    user: "root",
    password: "1234",
    database: "website"
});
app.set("view engine", "ejs");

app.get("/", (req, res)=>{
    const sql = "select * from website";
    connection.query(sql, (err, result, fields)=>{
        if(err)throw err;
        console.log(result);
    })
    res.render("index.ejs");  // デフォルトでは "/views"ディレクトリからの相対パスで表すので注意
})

app.listen(3000);

ターミナル上で$ node app.jsと入力し、Webブラウザでhttp://localhost:3000/にアクセスします。
前回と同様にHello WorldがWebブラウザに表示されており、
更にターミナル上に、次のような表示があれば成功です。

ここではconsole.log(result)の実行による、ターミナルのデータ出力結果から、
変数resultにはDBから取り出したデータが入っていることが確認できます。

$ node app.js
[
  RowDataPacket { name: 'google', url: 'https://www.google.com/' },
  RowDataPacket { name: 'amazon', url: 'https://www.amazon.co.jp/' },
  RowDataPacket { name: 'apple', url: 'https://www.apple.com/' },
  RowDataPacket { name: 'facebook', url: 'https://www.facebook.com/' }
]

3. DB内のデータをWebブラウザに表示してみる

『1.EJSでHello Worldしてみよう』, 『2.DBに接続してみよう』では、
res.render("index.ejs")とレンダリング先を表記し、ルーティングを設定していました。

今回はレンダリング先にデータを渡すために、
app.get()内にレンダリング先だけではなく、DBから取得したデータも記述する必要があります。
そこでres.render()の第二引数に、レンダリング先に送るデータを記述します。

より具体的にはいえば、
『2. DBに接続してみよう』で、変数resultにDBのデータが格納されることが確認できていました。
このresultをres.render()の第二引数に指定します。
従って、ここではres.render("index", { web: result})と記述します。

ところで{ web: result}という記述に、ややこしさを感じるかもしれません。
これはresultからwebへ名前を置換してから、データを送るという処理を含んでいます。

EJSに対して、resultという変数名をそのままに渡してしまうと、
「result?結果?いや何の結果を表す変数なのか、なんのこっちゃわからん」と、
フロントエンドエンジニアが困惑することになってしまいます。

(webという変数名ならば適切なのかという問題はさておき。)

実行するソースコード

DBに保存しているWebサイト名やURLをWebブラウザ上に出力するため、
app.jsindex.ejsを、それぞれ次のように書き換えます。

app.js
const express = require("express");
const app = express();
const mysql = require("mysql");
const connection = mysql.createConnection({
    host: "localhost",
    user: "root",
    password: "1234",
    database: "website"
});
app.set("view engine", "ejs");

app.get("/", (req, res)=>{
    const sql = "select * from website";
    connection.query(sql, (err, result, fields)=>{
        if(err)throw err;
        console.log(result);
        res.render("index", { web: result});
    })
})

app.listen(3000);
/views/index.ejs
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hello World</h1>
    <%= web %>
  </body>
</html>

ターミナルにnode app.jsを入力し、Webブラウザでhttp://localhost:3000/にアクセスします。
次の画像のような、Hello WorldとObjectという文字の羅列が確認できるでしょうか?
半分だけ成功です!

image.png

本来であればGoogleAppleといったWebサイト名や、
https://www.google.com/のようなURLがほしかったところですが、
DBから何らかのデータを取り出すことには、ひとまず成功したのではないでしょうか。
[]で囲まれたよくわからないものは4つで、DBに登録したレコードもちょうど4つでしたしね。

次の項で、この問題を解決します。

4. DB内のデータをWebブラウザに表示してみる(再挑戦)

前項ではDBから、どうやら何らかのデータを取り出すことには成功しましたが、
Webサイトの名前やURLを取得することはできませんでした。

この原因について考えます。

http://localhost:3000/にアクセスしたとき、
console.log(result)の実行によって、ターミナルに何か表示されたことは覚えているでしょうか?

それは、次のような内容でした。

$ node app.js
[
  RowDataPacket { name: 'google', url: 'https://www.google.com/' },
  RowDataPacket { name: 'amazon', url: 'https://www.amazon.co.jp/' },
  RowDataPacket { name: 'apple', url: 'https://www.apple.com/' },
  RowDataPacket { name: 'facebook', url: 'https://www.facebook.com/' }
]

一見するとオブジェクトですが、
出力されたデータは[]で囲まれているため、これはオブジェクトたちを格納している『配列』です

従って、例えばgoogleを取得する場合はweb[0]["name"]と記述します。

実行するソースコード

例として、googlehttps://www.google.com/をWebブラウザ上に表示してみます。
次のようにindex.ejsを書き換え、再度 $ node app.jsで実行します。
下記画像のように、Webサイト名とURLが表示されたら、成功です。

/views/index.ejs

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h1>Hello World</h1>
    <%= web[0]["name"] %>
    <br>
    <%= web[0]["url"] %>
  </body>
</html>

image.png

この他にも応用として、
for文を利用するなどして、一度に複数のデータを出力すること、
あるいはSQLを変更してデータの更新・追加・削除することも可能です。

おわりに

プログラミングを本格的に始めて1年も満たない未熟者の言葉ではありますが、
プログラミング言語の文法を修めるだけでは、Webのシステム開発は正直 不可能です。

私はJavaScriptの文法を学習した後、サーバーサイド言語としてのJavaScript(Node.js)に入門したのですが、
すぐにHTTPリクエスト、ルーティングなどといったWeb特有の専門用語に悩まされました。

Webアプリケーションのサーバーサイドへ入門する前に、
『この一冊で全部わかるWeb技術の基本』, 『Webを支える技術』, 『Web技術速習テキスト』といったWeb周りの情報に触れておくことを、強くおすすめします。

参考

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?