php editor Zimo is here to answer a common question: How to operate if you access the database in different modules? During the development process, we often need to access the database in different functional modules, which involves how to manage database connections and perform database operations. In order to solve this problem, we can use various methods, such as using global variables, singleton mode, dependency injection, etc. The specific method chosen depends on the needs of the project and the habits of the development team. Next, I will introduce these methods in detail, hoping to help everyone.
I'm trying to atuhorize using jwt but I'm having a problem, when I check the email for the value email from the statement I'm getting an error 500. The problem is because the database is not ready yet.
This is the code
Package route
package route import ( "go_fiber/controller" "go_fiber/middleware" "github.com/gofiber/fiber/v2" ) func routeinit(app *fiber.app, usercontroller controller.usercontroller) { app.get("/users", middleware.authmiddleware, usercontroller.findall) app.post("/login", usercontroller.login) }
Packaging Application
package app import ( "database/sql" "fmt" "go_fiber/helper" "os" "time" _ "github.com/go-sql-driver/mysql" "github.com/joho/godotenv" ) func newdb() *sql.db { var ( username = envvariable("db_username") password = envvariable("db_password") host = envvariable("db_host") port = envvariable("db_port") db_name = envvariable("db_name") ) dns := fmt.sprintf("%s:%s@tcp(%s:%s)/%s?parsetime=true", username, password, host, port, db_name) db, err := sql.open("mysql", dns) if err != nil { panic(err) } db.setmaxidleconns(10) db.setmaxopenconns(100) db.setconnmaxidletime(5 * time.minute) db.setconnmaxlifetime(60 * time.minute) return db }
包主
package main import ( "go_fiber/app" "go_fiber/controller" "go_fiber/exception" "go_fiber/repository" "go_fiber/route" "go_fiber/service" "github.com/go-playground/validator/v10" "github.com/gofiber/fiber/v2" ) func main(){ var db = app.newdb() app := fiber.new() app.use(func(c *fiber.ctx) error { defer func() { if err := recover(); err != nil { exception.errorhandler(c, err) } }() return c.next() }) validator := validator.new() userrepository := repository.newuserrepository() userservice := service.newuserservice(userrepository, db, validator) usercontroller := controller.newusercontroller(userservice) route.routeinit(app, usercontroller) app.listen(":3000") }
Encapsulation middleware
package middleware import ( "database/sql" "errors" "fmt" "go_fiber/exception" "log" "os" "time" "github.com/gofiber/fiber/v2" "github.com/golang-jwt/jwt/v4" ) func authmiddleware(c *fiber.ctx) error{ tokenstring := c.cookies("authorization") log.printf("(middleware) token : %v", tokenstring) if tokenstring == "" { panic(exception.newuserunauthorized(errors.new("user unauthorized").error())) } token, err := jwt.parse(tokenstring, func(token *jwt.token) (interface{}, error) { if _, ok := token.method.(*jwt.signingmethodhmac); !ok { return nil, fmt.errorf("unexpected signing method :%v", token.header["sub"]) } return []byte(os.getenv("secret")), nil }) log.printf("(middleware) token : %v", token) log.printf("(middleware) error : %v", err) if claims, ok := token.claims.(jwt.mapclaims); ok && token.valid { if float64(time.now().unix()) > claims["exp"].(float64) { panic(exception.newuserunauthorized(errors.new("user unauthorized").error())) } log.printf("(middleware) claims : %v", claims) log.printf("(middleware) ok : %v", ok) var db *sql.db tx, err := db.begin() log.printf("(middleware) tx : %v", tx) log.printf("(middleware) error : %v", err) query :=` select email from users where email = ? limit 1 ` log.printf("(middleware) query : %v", query) user, err := tx.querycontext(c.context(), query, claims["sub"]) log.printf("(middleware) user : %v", user) log.printf("(middleware) error : %v", err) if err != nil { panic(exception.newuserunauthorized(errors.new("user unauthorized").error())) } c.locals("user", user) c.next() }else { panic(exception.newuserunauthorized(errors.new("user unauthorized").error())) } return nil }
This part is the problem code
var db *sql.db tx, err := db.begin() log.printf("(middleware) tx : %v", tx) // no detect in terminal
This is the output of the log
2023/02/12 10:00:04 (middleware) token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzYxNzEzOTIsInN1YiI6IkphZmFyQGdtYWlsLmNvbSJ9.6nn_IaNACHfe7flFMOXfj1ygZS-U_yrnU_Gvjn8xCp8 2023/02/12 10:00:04 (middleware) token : &{eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NzYxNzEzOTIsInN1YiI6IkphZmFyQGdtYWlsLmNvbSJ9.6nn_IaNACHfe7flFMOXfj1ygZS-U_yrnU_Gvjn8xCp8 0xc0000a6780 map[alg:HS256 typ:JWT] map[exp:1.676171392e+09 sub:[email protected]] 6nn_IaNACHfe7flFMOXfj1ygZS-U_yrnU_Gvjn8xCp8 true} 2023/02/12 10:00:04 (middleware) error : <nil> 2023/02/12 10:00:04 (middleware) claims : map[exp:1.676171392e+09 sub:[email protected]] 2023/02/12 10:00:04 (middleware) ok : true
So, how to solve the problem of accessing the database if different packages are used?
You should pass the database handler down to the middleware via route registration.
Change your authmiddleware so that it is returned by a function that takes db *sql.db as a parameter:
func newauthmiddleware(db *sql.db) fiber.handler { return func(c *fiber.ctx) error { // the rest of your function is here and has access to db } }
Then you need to call newauthmiddleware
in the routeinit functionfunc routeinit(app *fiber.app, usercontroller controller.usercontroller, db *sql.db) { app.get("/users", middleware.newauthmiddleware(db), usercontroller.findall) app.post("/login", usercontroller.login) }
Then pass the database to routeinit()
in the main functionfunc main() { // ... as before route.RouteInit(app, userController, db) }
The above is the detailed content of How to access the database if the functions are in different modules?. For more information, please follow other related articles on the PHP Chinese website!