Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8837

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

$
0
0

はじめに

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

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
constexpress=require("express");constapp=express();app.get("/",(req,res)=>{consttext="Hello World";letdata="<!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+=textdata+="</p>\r\n";data+="</body>\r\n";data+="</html>";res.send(data);});app.listen(3000);

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

app.js
constexpress=require("express");constapp=express();app.set("view engine","ejs");app.get("/",(req,res)=>{consttext="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
constexpress=require("express");constapp=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
constexpress=require("express");constapp=express();constmysql=require("mysql");constconnection=mysql.createConnection({host:"localhost",user:"root",password:"1234",database:"website"});app.set("view engine","ejs");app.get("/",(req,res)=>{constsql="select * from website";connection.query(sql,(err,result,fields)=>{if(err)throwerr;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
constexpress=require("express");constapp=express();constmysql=require("mysql");constconnection=mysql.createConnection({host:"localhost",user:"root",password:"1234",database:"website"});app.set("view engine","ejs");app.get("/",(req,res)=>{constsql="select * from website";connection.query(sql,(err,result,fields)=>{if(err)throwerr;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周りの情報に触れておくことを、強くおすすめします。

参考


Viewing all articles
Browse latest Browse all 8837

Trending Articles