【问题标题】:Where to place code to show data from MySQL to Handlebars?在哪里放置代码以显示从 MySQL 到 Handlebars 的数据?
【发布时间】:2020-11-01 09:47:31
【问题描述】:

目标:

我的目标是自学如何使用 Node JS、MySQL 和 express。

我很难理解将 MySQL 数据加载到 HTML 中的代码的放置位置。

让我给你看整个代码。

app.js

var express = require('express');

var mysql = require('mysql');
var dotenv = require('dotenv');
var path = require('path');
var cookieParser = require('cookie-parser');

dotenv.config({path: './.env'});


var app = express();

// Connection to MySQL
var db = mysql.createConnection({
  host: process.env.DATABASE_HOST,
  user: process.env.DATABASE_USER,
  password:  process.env.DATABASE_PASSWORD,
  database: process.env.DATABASE
});

db.connect(function(error) {
  if(error) {
    console.log(error);
  }
  else{
    console.log("Connected");
  }
});

// Parse URL-Encoded bodies
app.use(express.urlencoded({extended: false}));
// Parse JSON bodies
app.use(express.json());
// Initialize a cookie
app.use(cookieParser());

// View engine to control HTML
app.set('view engine', 'hbs');

// Public dir
var publicDir = path.join(__dirname, './public');
app.use(express.static(publicDir));

// Define routes
app.use('/', require('./routes/pages'));
app.use('/auth', require('./routes/auth'));

app.listen(3000, function() {
  console.log("Server is running on port 3000");
});

routes/pages.js

var express = require('express');
var authController = require('../controllers/auth');

var router = express.Router();

// Home
router.get("/", authController.isLoggedIn, function(req,res) {
  res.render("index", {
    user: req.user
  });
});

// Register
router.get("/register", function(req, res) {
  res.render("register");
});

// Login
router.get("/login", function(req, res) {
  res.render("login");
});

// Profile
router.get('/profile', authController.isLoggedIn, function(req, res) {
  if(req.user) {
    res.render('profile', {
      user: req.user
    });
  }
  else {
    res.redirect('login');
  }

});

// Forum
router.get('/forums', authController.isLoggedIn, function(req, res) {
  if(req.user) {
    res.render('forums');
  } else {
    res.redirect('login');
  }
});

// English Division //

// Premier League
router.get('/Leagues/EnglishDivision', authController.isLoggedIn,  function(req, res) {
  if(req.user) {
    res.render('PremierLeague');

  } else {
    res.redirect('../../login');
  }
});


module.exports = router;

routes/auth.js

var express = require('express');
var authController = require('../controllers/auth');

var router = express.Router();

// Register
router.post("/register", authController.register);

// Login
router.post("/login", authController.login);

// Logout
router.get('/logout', authController.logout);

module.exports = router;

controllers/auth.js

var mysql = require('mysql');
var jwt = require('jsonwebtoken');
var bcrypt = require('bcryptjs');
var {promisify} = require('util');


// Connection to MySQL
var db = mysql.createConnection({
  host: process.env.DATABASE_HOST,
  user: process.env.DATABASE_USER,
  password:  process.env.DATABASE_PASSWORD,
  database: process.env.DATABASE
});

// Register function
exports.register = function(req, res) {
  console.log(req.body);

  var {name, email, password, passwordConfirm} = req.body;

  db.query("SELECT email FROM users WHERE email = ?", [email], function(error, result) {
    if(error){
      console.log(error);
    }

    if(result.length > 0) {
      return res.render('register', {
        message: 'That email is already in use'
      })
    } else if(password !== passwordConfirm) {
      return res.render('register', {
        message: 'Passwords do not match'
      });
    }

    let hashedPassword = bcrypt.hashSync(password, 8);
    console.log(hashedPassword);

    // Insert user details into MySQL
    db.query('INSERT INTO users set ?', {name: name, email: email, password: hashedPassword, dateJoined: new Date()}, function(error, result) {
      if(error) {
        console.log(error);
      } else {
        console.log(result);
        return res.render('register', {
          message: 'User registered'
        });
      }
    });
  });
}


// Login function

exports.login = function(req, res) {
  try {

    var {email, password} = req.body;

    if(!email || !password) {
      return res.status(400).render('login', {
        message: 'Please provide an email and password'
      });
    }

    db.query('SELECT * FROM users WHERE email = ?', [email], async function(error, result) {

      console.log(result);

      if(!result.length > 0 || !(await bcrypt.compare(password, result[0].password))) {
        res.status(401).render('login', {
          message: 'The email or password is incorrect'
        });
      }


      else {

        var id = result[0].id;

        // Create a token
        var token = jwt.sign({id}, process.env.JWT_SECRET, {
          expiresIn: process.env.JWT_EXPIRES_IN
        });

        console.log("The token is " + token);

        // Create a cookie
        var cookieOptions = {
          expires: new Date(
            Date.now() + process.env.JWT_COOKIE_EXPIRES * 24 * 60 * 60 * 1000
          ),
          httpOnly: true
        }

        // Set up a cookie
        res.cookie('jwt', token, cookieOptions);
        res.status(200).redirect("/");

      }
    });


  } catch (error) {
    console.log(error);
  }
}

// Check if logged in
exports.isLoggedIn = async function(req, res, next) {
  console.log(req.cookies);
  if(req.cookies.jwt){
    try {
      // Verify the token
      var decoded = await promisify(jwt.verify)(req.cookies.jwt, process.env.JWT_SECRET);

      console.log(decoded);

      // Check if user exist
      db.query("SELECT id, name, email, password, date_format(datejoined, '%d/%m/%Y') as dateJoined FROM users WHERE id = ?", [decoded.id], function(error, result) {
        console.log(result);

        // If no result
        if(!result) {
          return next();
        }

        req.user = result[0];
        return next();

      });
    }
  catch (e) {
    console.log(e);
    return next();
  }
} else{
    next();
  }
}

// Logout function
exports.logout = async function(req, res) {
  res.clearCookie('jwt');
  res.status(200).redirect('/');
}

问题

在我的.hbs 文件PremierLeague 中,我想以HTML 格式加载MySQL 数据。下面的代码我需要从哪里开始?

预期目标:

这是用户点击查看英超联赛的时间

MySQL 中的 Foreach 记录 我想为每条记录添加一张新卡。我知道如何使用 HandleBars {{some.data}}

  • 我只是不知道在哪里编写查询代码?
  • 它需要在控制器中还是可以在router.get(... 中?
  • 另外我该如何正确使用{{#foreach}}

【问题讨论】:

    标签: mysql node.js


    【解决方案1】:

    您不需要任何其他特定的控制器,对查询进行编码的正确位置实际上是路由本身。

    但是在进入你的问题的核心之前,让我们先谈谈你的代码。

    我可以看到您不止一次执行与数据库的连接,您可以添加数据库专用控制器,例如:

    controllers/db.js

    var mysql = require('mysql');
    var dotenv = require('dotenv');
    
    dotenv.config({path: './.env'});
    
    // Connection to MySQL
    var db = mysql.createConnection({
      host:     process.env.DATABASE_HOST,
      user:     process.env.DATABASE_USER,
      password: process.env.DATABASE_PASSWORD,
      database: process.env.DATABASE
    });
    
    function connect(done) {
      db.connect(done);
    }
    
    module.exports = { db: db, connect: connect };
    

    这让您只需一行即可从每个文件访问数据库实例:

    var db = require('./controllers/db').db;
    

    您可以在您的应用中使用connect 函数:

    app.js

    var express = require('express');
    var db = require(./controllers/db);
    var path = require('path');
    var cookieParser = require('cookie-parser');
    
    // set up your server
    var app = express();
    
    // Parse URL-Encoded bodies
    app.use(express.urlencoded({extended: false}));
    // Parse JSON bodies
    app.use(express.json());
    // Initialize a cookie
    app.use(cookieParser());
    
    // View engine to control HTML
    app.set('view engine', 'hbs');
    
    // Public dir
    var publicDir = path.join(__dirname, './public');
    app.use(express.static(publicDir));
    
    // Define routes
    app.use('/', require('./routes/pages'));
    app.use('/auth', require('./routes/auth'));
    
    // finally run your server only if you can connect to the database
    db.connect(function(error) {
      if(error) return console.log("Error connecting to the database:", error);
    
      app.listen(3000, function() {
        console.log("Server is running on port 3000");
      });
    });
    

    您还可以简化 controllers/auth.js 删除数据库连接内容并仅使用需要数据库控制器的行。

    最后,您可以编写查询代码:

    routes/pages.js

    var express = require('express');
    var authController = require('../controllers/auth');
    var db = require('../controllers/db').db;
    
    var router = express.Router();
    
    // Omissis... other routes
    
    // Premier League
    router.get('/Leagues/EnglishDivision', authController.isLoggedIn, function(req, res) {
      // a good practice is first to handle possible exit cases to reduce nesting levels
      if(! req.user) return res.redirect('../../login');
    
      // this is actually the right place to perform queries
      db.query('SELECT ...', [...], function(error, results) {
        // once again first possible exit cases
        if(error) return res.status(500).end(error.message)
    
        res.render('PremierLeague', { results: results });
      });
    });
    
    module.exports = router;
    

    最后在您的 PremierLeague.hbs 文件中,您可以在 #foreach 指令中处理 results

    【讨论】:

    • 您好,感谢您的回答!关于来自控制器的数据库连接。我将var db = require('../controllers/db').db; 放入app.js。它带有错误Error: Cannot find module '/controllers/db'。结构如下。 app.js 和另一个名为 controllers 的文件夹与 app.js 在同一级别。
    • 检查路径@LV98 ;) require('./controllers/db')
    • 真的很喜欢在控制器中设置数据库的想法。感谢那。现在要继续阅读您的其他 cmets :D
    • 你能举一个在#foreach 中处理results 的例子吗?我尝试了以下方法:stackoverflow.com/a/44715431/12485722
    • 如果您想将user 数据添加到模板以渲染某些内容(例如名称)@LV98,您必须将其作为{ result: result, user: req.user } 传递给模板
    【解决方案2】:

    在渲染视图时传递数据

        router.get('/Leagues/EnglishDivision', authController.isLoggedIn,  function(req, res) {
          if(req.user) {
           connection.query('SELECT * FROM EnglishDivision',function (err,results) {
            if (err) throw err;
            res.render('PremierLeague',{data: results});
        });
     
          } else {
            res.redirect('../../login');
          }
        });
    

    然后在.hbs文件中

      {{#each data}}
                    <div class="card">
                        <h3>{{this.someData}}</h3>
                        <h2>{{this.someData}}</h2>
                    </div>
                {{/each}}
    

    【讨论】:

    • 我需要另一个控制器吗?或者是否值得在渲染中进行查询?
    猜你喜欢
    • 1970-01-01
    • 2012-12-24
    • 2015-10-31
    • 1970-01-01
    • 2019-11-24
    • 2015-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多