首页  >  文章  >  后端开发  >  有条件地执行多个模板

有条件地执行多个模板

王林
王林转载
2024-02-09 11:48:09340浏览

有条件地执行多个模板

php小编鱼仔为您介绍一种强大的技术:有条件地执行多个模板。在开发网站时,我们常常需要根据不同的条件动态地加载不同的模板文件,这就是有条件地执行多个模板的应用场景。通过使用这种技术,我们可以根据用户的登录状态、权限等条件来动态地加载相应的模板文件,从而实现更灵活、个性化的网站界面。这种技术不仅提高了网站的可扩展性和可维护性,还能为用户提供更好的使用体验。在本文中,我们将详细介绍如何使用php实现有条件地执行多个模板的方法,帮助您更好地应用于实际项目中。

问题内容

我有一个具有两种视图的网页,一种用于匿名用户,一种用于管理员用户。我想仅为管理员用户显示导航栏。对于两种用户类型,其他一切都保持不变。

这是我迄今为止尝试过的

main.go

package main

import (
    "log"
    "net/http"
    "text/template"

    "github.com/julienschmidt/httprouter"
)

func basicauth(h httprouter.handle, requireduser, requiredpassword string) httprouter.handle {
    return func(w http.responsewriter, r *http.request, ps httprouter.params) {
        // get the basic authentication credentials
        user, password, hasauth := r.basicauth()

        if hasauth && user == requireduser && password == requiredpassword {
            // delegate request to the given handle
            h(w, r, ps)
        } else {
            // request basic authentication otherwise
            w.header().set("www-authenticate", "basic realm=restricted")
            http.error(w, http.statustext(http.statusunauthorized), http.statusunauthorized)
        }
    }
}

func anonymous(w http.responsewriter, r *http.request, _ httprouter.params) {
    t, err := template.parsefiles("index.html")
    if err != nil {
        log.fatalln(err)
    }
    err = t.execute(w, map[string]string{"name": "anonymous"})
    if err != nil {
        log.fatalln(err)
    }
}

func admin(w http.responsewriter, r *http.request, _ httprouter.params) {
    t, err := template.parsefiles("index.html", "admin.html")
    if err != nil {
        log.fatalln(err)
    }
    err = t.execute(w, map[string]string{"name": "admin"})
    if err != nil {
        log.fatalln(err)
    }
}

func main() {
    user := "admin"
    pass := "1234"

    router := httprouter.new()
    router.get("/", anonymous)
    router.get("/admin/", basicauth(admin, user, pass))

    log.fatal(http.listenandserve(":8080", router))
}

index.html

<!doctype html>
<html lang="en">
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{ .name }}</title>
        <link href="https://cdn.jsdelivr.net/npm/[email&#160;protected]/dist/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.jsdelivr.net/npm/[email&#160;protected]/dist/js/bootstrap.bundle.min.js"></script>
        <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
        <script>
            function counter() {
                document.getelementbyid("x").innerhtml = "x: " + document.queryselectorall('.x').length;
                document.getelementbyid("y").innerhtml = "y: " + document.queryselectorall('.y').length;
                document.getelementbyid("z").innerhtml = "z: " + document.queryselectorall('.z').length;
            }
        </script>
    </head>
    <body onload="counter()">
        {{ template "dashboard" }}
        <nav class="navbar fixed-bottom">
            <div class="container-fluid nav-justified">
                <span id="x" class="navbar-brand nav-item"></span>
                <span id="y" class="navbar-brand nav-item"></span>
                <span id="z" class="navbar-brand nav-item"></span>
            </div>
        </nav>
    </body>
</html>

admin.html

{{ define "dashboard" }}
<nav class="navbar">
    <div class="container-fluid nav-justified">
        <span class="nav-item">
            <a class="navbar-brand" href="/a">a</a>
        </span>
        <span class="nav-item">
            <a class="navbar-brand" href="/b">b</a>
        </span>
        <span class="nav-item">
            <a class="navbar-brand" href="/c">c</a>
        </span>
    </div>
</nav>
{{ end }}

我的假设是,因为我在为匿名用户执行模板时没有传入 admin.html 模板,所以仪表板模板不会被解析。但是,我遇到了这个错误:

template: index.html:18:14: executing "index.html" at <{{template "dashboard"}}>: template "dashboard" not defined

如何解决这个问题,或者有更好的方法吗?

解决方法

使用 if 操作有条件地渲染 dashboard 模板:

{{ if eq .name "admin" }} {{ template "dashboard" }} {{ end }}

实践是只解析模板一次,而不是在每个请求时都解析它:

package main

import (
    "log"
    "net/http"
    "sync"
    "text/template"

    "github.com/julienschmidt/httprouter"
)

func BasicAuth(h httprouter.Handle, requiredUser, requiredPassword string) httprouter.Handle {
    return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
        user, password, hasAuth := r.BasicAuth()

        if hasAuth && user == requiredUser && password == requiredPassword {
            h(w, r, ps)
        } else {
            w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
            http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
        }
    }
}

func Anonymous(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    err := tmpl.Execute(w, map[string]string{"Name": "Anonymous"})
    if err != nil {
        log.Fatalln(err)
    }
}

func Admin(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    err := tmpl.Execute(w, map[string]string{"Name": "Admin"})
    if err != nil {
        log.Fatalln(err)
    }
}

var (
    tmpl     *template.Template
    tmplOnce sync.Once
)

func main() {
    user := "admin"
    pass := "1234"

    tmplOnce.Do(func() {
        tmpl = template.Must(template.ParseFiles("index.html", "admin.html"))
    })

    router := httprouter.New()
    router.GET("/", Anonymous)
    router.GET("/admin/", BasicAuth(Admin, user, pass))

    log.Fatal(http.ListenAndServe(":8080", router))
}

以上是有条件地执行多个模板的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文转载于:stackoverflow.com。如有侵权,请联系admin@php.cn删除