Nodejs MySQLは、JSとMySQLのノードを使用して簡単なアプリをビルドします.


こんにちは.このチュートリアルでは、ノードJSとMySQLを使用して簡単なCRUDアプリケーションを構築します.

我々は何を構築するか?

上記のイメージは、アプリを示しています.これは、データベースに選手を追加することもできますし、データベースから自分の詳細を表示できるアプリケーションです.また、削除することができますし、プレーヤーの詳細を編集します.

必要条件
このチュートリアルに参加する前に、以下の要件を満たしていると仮定します.
あなたのPCにインストールされる
  • ノードJS.
  • ノードJSとExpress JSの基本的な理解.
  • SQLの知識は、データベースのクエリ方法を知り、理解する必要があります.
  • あなたのPCにインストールされる
  • phpMyAdmin .私は、それにすでにPhpMyAdminを含むので、xamppをインストールすることを勧めます.
  • テンプレートエンジンの使い方を理解しています--このチュートリアルでは、EJSを使用する予定です.
  • あなたの選択のテキストエディタまたはIDE.

  • フォルダ構造
    プロジェクトがどのように構造化されるかです.
    ├── node-mqsql-crud-app (main directory)   
        ├── node_modules
        ├── public
            ├── assets 
                ├── img
        ├── routes
            ├── index.js
            ├── player.js
        ├── views
            ├── partials 
                ├── header.ejs
            ├── index.ejs
            ├── add-player.ejs
            ├── edit-player.ejs
        ├── app.js    
    

    プロジェクト用ディレクトリの作成
    コマンドプロンプトを適当なディレクトリに開き、次のコマンドを入力します.
    mkdir node-mysql-crud-app 
    
    次に、次のコマンドを入力してディレクトリに移動します
    cd node-mysql-crud-app 
    

    プロジェクトの初期化
    コマンドプロンプトをプロジェクトディレクトリに開き、以下のコマンドを入力します.
    npm init
    

    必須モジュールをインストールします.
    以下のモジュールは、正常にアプリケーションを構築するために必要になります.

  • express :クライアントからハンドルルーティングとプロセスリクエストを作成するために使用します.

  • express-fileupload : Busboyを包む単純なExpressファイルのアップロードミドルウェア.

  • body-parser :クライアントからの着信要求を解析するために使用します.

  • mysql : MySQL用のノードJSドライバ.

  • ejs :アプリのHTMLページをレンダリングするエンジンをテンプレートします.

  • req-flash :ビュー
  • にフラッシュメッセージを送信するために使用されます

  • nodemon :世界的に設置.これは、ファイルへの変更を監視し、自動的にサーバーを再起動するために使用されます.
  • 最初の7モジュールを依存関係としてインストールするには、次のコマンドを入力します.
    npm install express express-fileupload body-parser mysql ejs req-flash --save
    
    次に、次のコマンドを入力して、PC上で最後にモジュールをインストールします.
    npm install nodemon -g
    

    アプリのデータベースを作成する
    以下のコマンドをコピーして、phpMyAdminダッシュボードに移動して、コンソールの中で次のクエリーを実行します(通常、ページの一番下にあります).
    CREATE DATABASE socka;
    CREATE TABLE IF NOT EXISTS `players` (
      `id` int(5) NOT NULL AUTO_INCREMENT,
      `first_name` varchar(255) NOT NULL,
      `last_name` varchar(255) NOT NULL,
      `position` varchar(255) NOT NULL,
      `number` int(11) NOT NULL,
      `image` varchar(255) NOT NULL,
      `user_name` varchar(20) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;
    

    ビューの追加

    ヘッダ.EJS
    ヘッダ.EJSファイルは/etc/partialsフォルダにあるでしょう.
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
        <!--<link rel="stylesheet" href="/assets/css/custom.css">-->
        <title><%= title %></title>
    </head>
    <style>
        .table-wrapper {
            margin-top: 50px;
        }
    
        .player-img {
            width: 40px;
            height: 40px;
        }
    
        .add-player-form {
            margin-top: 50px;
        }
    </style>
    <body>
    <div class="page-wrapper">
        <nav class="navbar navbar-light bg-light">
            <span class="navbar-brand mb-0 h1" ><a href="/">Socka Players</a></span>
            <a class="float-right" href="/add" title="Add a New Player">Add a Player</a>
        </nav>
    

    インデックス.EJS

    This is the homepage of the app which contains a table to display a list of all the players.


    <% include partials/header.ejs %>
        <div class="table-wrapper">
            <% if (players.length > 0) {%>
                <table class="table table-hovered">
                    <thead class="thead-dark">
                        <tr>
                            <th scope="col">ID</th>
                            <th scope="col">Image</th>
                            <th scope="col">First Name</th>
                            <th scope="col">Last Name</th>
                            <th scope="col">Position</th>
                            <th scope="col">Number</th>
                            <th scope="col">Username</th>
                            <th scope="col">Action</th>
                        </tr>
                    </thead>
                    <tbody>
                        <% players.forEach((player, index) => { %>
                            <tr>
                                <th scope="row"><%= player.id %></th>
                                <td><img src="/assets/img/<%= player.image %>" class="rounded-circle player-img" alt=""></td>
                                <td><%= player.first_name %></td>
                                <td><%= player.last_name %></td>
                                <td><%= player.position %></td>
                                <td><%= player.number %></td>
                                <td>@<%= player.user_name %></td>
                                <td>
                                    <a href="/edit/<%= player.id %>" target="_blank" rel="noopener" class="btn btn-sm btn-success">Edit</a>
                                    <a href="/delete/<%= player.id %>" class="btn btn-sm btn-danger">Delete</a>
                                </td>
                            </tr>
                        <% }) %>
                    </tbody>
                </table>
            <% } else { %>
                <p class="text-center">No players found. Go <a href="/add" >here</a> to add players.</p>
            <% } %>
        </div>
    </div>
    </body>
    </html>
    
    

    プレーヤーを追加します.EJS

    This page contains the form to add a new player to the database.


    <% include partials/header.ejs %>
        <div class="container">
            <% if (message != '') { %>
                <p class="text-center text-danger"><%= message %></p>
            <% } %>
            <form class="add-player-form" action="" method="post" enctype="multipart/form-data">
                <div class="form-row">
                    <div class="form-group col-md-4">
                        <input type="text" class="form-control" name="first_name" id="first-name" placeholder="First Name" required>
                    </div>
                    <div class="form-group col-md-4">
                        <input type="text" class="form-control" name="last_name" id="last-name" placeholder="Last Name" required>
                    </div>
                    <div class="form-group col-md-4">
                        <input type="text" class="form-control" name="username" id="username" placeholder="Username" required>
                    </div>
                </div>
                <div class="form-row">
                    <div class="form-group col-md-6">
                        <input type="number" class="form-control" name="number" id="number" placeholder="Number" required>
                    </div>
                    <div class="form-group col-md-6">
                        <select id="position" name="position" class="form-control" required>
                            <option selected disabled>Choose position</option>
                            <option>Goalkeeper</option>
                            <option>Defender</option>
                            <option>Midfielder</option>
                            <option>Forward</option>
                        </select>
                    </div>
                    <div class="col-md-12">
                        <label for="player-img"><b>Player Image</b></label><br>
                        <input type="file" name="image" id="player-img" class="" required>
                    </div>
                </div>
                <button type="submit" class="btn btn-primary float-right">Add Player</button>
            </form>
        </div>
    </div>
    </body>
    </html>
    
    

    エディット.EJS

    This page contains the form to edit a player added to the database.


    <% include partials/header.ejs %>
    <div class="container">
        <% if (message) { %>
            <p class="text-center text-danger"><%= message %></p>
        <% } %>
    
        <% if (player) { %>
            <form class="add-player-form" action="" method="post" enctype="multipart/form-data">
                <div class="form-row">
                    <div class="form-group col-md-4">
                        <label for="first-name">First Name</label>
                        <input type="text" class="form-control" name="first_name" id="first-name" value="<%= player.first_name %>" required>
                    </div>
                    <div class="form-group col-md-4">
                        <label for="last-name">Last Name</label>
                        <input type="text" class="form-control" name="last_name" id="last-name" value="<%= player.last_name %>" required>
                    </div>
                    <div class="form-group col-md-4">
                        <label for="username">Username</label>
                        <input type="text" class="form-control" name="username" id="username" value="<%= player.user_name %>" required disabled title="Username cannot be edited.">
                    </div>
                </div>
                <div class="form-row">
                    <div class="form-group col-md-6">
                        <label for="number">Number</label>
                        <input type="number" class="form-control" name="number" id="number" placeholder="Number" value="<%= player.number %>" required>
                    </div>
                    <div class="form-group col-md-6">
                        <label for="position">Position</label>
                        <select id="position" name="position" class="form-control" required>
                            <option selected><%= player.position %></option>
                            <option>Goalkeeper</option>
                            <option>Centre Back</option>
                            <option>Right Back</option>
                            <option>Left Back</option>
                            <option>Defensive Midfielder</option>
                            <option>Central Midfielder</option>
                            <option>Attacking Midfielder</option>
                            <option>Right Wing Forward</option>
                            <option>Left Wing Forward</option>
                            <option>Striker</option>
                        </select>
                    </div>
                </div>
                <button type="submit" class="btn btn-success float-right">Update Player</button>
            </form>
        <% } else { %>
            <p class="text-center">Player Not Found. Go <a href="/add">here</a> to add players.</p>
        <% } %>
    </div>
    </div>
    </body>
    </html>
    

    サーバー上での作業

    アプリ.js
    const express = require('express');
    const fileUpload = require('express-fileupload');
    const bodyParser = require('body-parser');
    const mysql = require('mysql');
    const path = require('path');
    const app = express();
    
    // const {getHomePage} = require('./routes/index');
    // const {addPlayerPage, addPlayer, deletePlayer, editPlayer, editPlayerPage} = require('./routes/player');
    const port = 5000;
    
    // create connection to database
    // the mysql.createConnection function takes in a configuration object which contains host, user, password and the database name.
    const db = mysql.createConnection ({
        host: 'localhost',
        user: 'root',
        password: '',
        database: 'socka'
    });
    
    // connect to database
    db.connect((err) => {
        if (err) {
            throw err;
        }
        console.log('Connected to database');
    });
    global.db = db;
    
    // configure middleware
    app.set('port', process.env.port || port); // set express to use this port
    app.set('views', __dirname + '/views'); // set express to look in this folder to render our view
    app.set('view engine', 'ejs'); // configure template engine
    app.use(bodyParser.urlencoded({ extended: false }));
    app.use(bodyParser.json()); // parse form data client
    app.use(express.static(path.join(__dirname, 'public'))); // configure express to use public folder
    app.use(fileUpload()); // configure fileupload
    
    // routes for the app
    /*
    app.get('/', getHomePage);
    app.get('/add', addPlayerPage);
    app.get('/edit/:id', editPlayerPage);
    app.get('/delete/:id', deletePlayer);
    app.post('/add', addPlayer);
    app.post('/edit/:id', editPlayer);
    */
    
    // set the app to listen on the port
    app.listen(port, () => {
        console.log(`Server running on port: ${port}`);
    });
    
    

    In the above code, the modules are required and then a connection to the database is created. The mysql.createConnection function takes in an object which contains the configuration of the database being connected to. In the next statement, the database is being connected. Run the code below on the command prompt to run the server.


    nodemon app.js
    
    コンソールは以下の結果を表示します.


    ルートの追加

    インデックス.js
    以下のコードをインデックスにコピーします./ディレクトリディレクトリのjsファイル.
    module.exports = {
        getHomePage: (req, res) => {
            let query = "SELECT * FROM `players` ORDER BY id ASC"; // query database to get all the players
    
            // execute query
            db.query(query, (err, result) => {
                if (err) {
                    res.redirect('/');
                }
                res.render('index.ejs', {
                    title: Welcome to Socka | View Players
                    ,players: result
                });
            });
        },
    };
    
    

    The db.query function queries the database. It takes in the query and string and a callback which takes in two parameters, if the query is successful, the result is passed to the view in the res.render function.



    プレーヤー.js
    選手.JSファイルは、プレーヤーの追加、プレーヤーの詳細を更新し、プレーヤーを削除などのプレーヤーのページのすべてのルートを含むようになります.
    const fs = require('fs');
    
    module.exports = {
        addPlayerPage: (req, res) => {
            res.render('add-player.ejs', {
                title: Welcome to Socka | Add a new player
                ,message: ''
            });
        },
        addPlayer: (req, res) => {
            if (!req.files) {
                return res.status(400).send("No files were uploaded.");
            }
    
            let message = '';
            let first_name = req.body.first_name;
            let last_name = req.body.last_name;
            let position = req.body.position;
            let number = req.body.number;
            let username = req.body.username;
            let uploadedFile = req.files.image;
            let image_name = uploadedFile.name;
            let fileExtension = uploadedFile.mimetype.split('/')[1];
            image_name = username + '.' + fileExtension;
    
            let usernameQuery = "SELECT * FROM `players` WHERE user_name = '" + username + "'";
    
            db.query(usernameQuery, (err, result) => {
                if (err) {
                    return res.status(500).send(err);
                }
                if (result.length > 0) {
                    message = 'Username already exists';
                    res.render('add-player.ejs', {
                        message,
                        title: Welcome to Socka | Add a new player
                    });
                } else {
                    // check the filetype before uploading it
                    if (uploadedFile.mimetype === 'image/png' || uploadedFile.mimetype === 'image/jpeg' || uploadedFile.mimetype === 'image/gif') {
                        // upload the file to the /public/assets/img directory
                        uploadedFile.mv(`public/assets/img/${image_name}`, (err ) => {
                            if (err) {
                                return res.status(500).send(err);
                            }
                            // send the player's details to the database
                            let query = "INSERT INTO `players` (first_name, last_name, position, number, image, user_name) VALUES ('" +
                                first_name + "', '" + last_name + "', '" + position + "', '" + number + "', '" + image_name + "', '" + username + "')";
                            db.query(query, (err, result) => {
                                if (err) {
                                    return res.status(500).send(err);
                                }
                                res.redirect('/');
                            });
                        });
                    } else {
                        message = "Invalid File format. Only 'gif', 'jpeg' and 'png' images are allowed.";
                        res.render('add-player.ejs', {
                            message,
                            title: Welcome to Socka | Add a new player
                        });
                    }
                }
            });
        },
        editPlayerPage: (req, res) => {
            let playerId = req.params.id;
            let query = "SELECT * FROM `players` WHERE id = '" + playerId + "' ";
            db.query(query, (err, result) => {
                if (err) {
                    return res.status(500).send(err);
                }
                res.render('edit-player.ejs', {
                    title: Edit  Player
                    ,player: result[0]
                    ,message: ''
                });
            });
        },
        editPlayer: (req, res) => {
            let playerId = req.params.id;
            let first_name = req.body.first_name;
            let last_name = req.body.last_name;
            let position = req.body.position;
            let number = req.body.number;
    
            let query = "UPDATE `players` SET `first_name` = '" + first_name + "', `last_name` = '" + last_name + "', `position` = '" + position + "', `number` = '" + number + "' WHERE `players`.`id` = '" + playerId + "'";
            db.query(query, (err, result) => {
                if (err) {
                    return res.status(500).send(err);
                }
                res.redirect('/');
            });
        },
        deletePlayer: (req, res) => {
            let playerId = req.params.id;
            let getImageQuery = 'SELECT image from `players` WHERE id = "' + playerId + '"';
            let deleteUserQuery = 'DELETE FROM players WHERE id = "' + playerId + '"';
    
            db.query(getImageQuery, (err, result) => {
                if (err) {
                    return res.status(500).send(err);
                }
    
                let image = result[0].image;
    
                fs.unlink(`public/assets/img/${image}`, (err) => {
                    if (err) {
                        return res.status(500).send(err);
                    }
                    db.query(deleteUserQuery, (err, result) => {
                        if (err) {
                            return res.status(500).send(err);
                        }
                        res.redirect('/');
                    });
                });
            });
        }
    };
    
    

    This file handles all the post and get requests for the players page. The add player function contains a function that uploads the player's image to the /public/assets/img directory and sends the player's details to the database.



    ルートとビューの接続
    アプリに移動します.以下の行をコメントしないでください
    ライン8と9の上の

  • // const {getHomePage} = require('./routes/index');
    // const {addPlayerPage, addPlayer, deletePlayer, editPlayer, editPlayerPage} = require('./routes/player');
    
    ライン40 - 47の

  • /*
    app.get('/', getHomePage);
    app.get('/add', addPlayerPage);
    app.get('/edit/:id', editPlayerPage);
    app.get('/delete/:id', deletePlayer);
    app.post('/add', addPlayer);
    app.post('/edit/:id', editPlayer);
    */
    

    アプリの実行
    コメント行を削除した後、コマンドプロンプトをチェックしてコードにエラーがないことを確認し、ブラウザに頭を開き、http://localhost:5000を開きます.インデックスページが表示され、プレーヤーが追加されていないため、ページは以下のようになります.

    ページのプレーヤーリンクを追加するには、プレーヤーのページをロードし、プレーヤーを追加するフォームを入力します.プレーヤーを追加した後、ホームページが表示されます選手がテーブルに追加されました.このように

    エラーが発生した場合は、コメントセクションで注意を引いたり、プロジェクトのRIPOをgithubで確認してください.
    コードは完璧ではありませんし、それが良いとプル要求を送信すること自由に感じてください.
    または私にチェックアウトすることを忘れないでください.