mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 10:41:03 +01:00
Nothing in codebase, just some MVC examples enhancements
Former-commit-id: 81f1121da0e7632ef3a0f7b78d6784ee1690eb7e
This commit is contained in:
parent
32d14db46d
commit
13975a5d81
69
HISTORY.md
69
HISTORY.md
|
@ -499,68 +499,7 @@ However two more methods added to the `Controller`.
|
||||||
- `RelTmpl() string`, returns the relative template directory based on the controller's name.
|
- `RelTmpl() string`, returns the relative template directory based on the controller's name.
|
||||||
|
|
||||||
These are useful when dealing with big `controllers`, they help you to keep align with any
|
These are useful when dealing with big `controllers`, they help you to keep align with any
|
||||||
future changes inside your application.
|
future changes inside your application.
|
||||||
|
|
||||||
Let's refactor our [ProfileController](_examples/mvc/controller-with-model-and-view/main.go) enhancemed by these two new functions.
|
|
||||||
|
|
||||||
```go
|
|
||||||
func (pc *ProfileController) tmpl(relativeTmplPath string) {
|
|
||||||
// the relative template files directory of this controller.
|
|
||||||
views := pc.RelTmpl()
|
|
||||||
pc.Tmpl = views + relativeTmplPath
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pc *ProfileController) match(relativeRequestPath string) bool {
|
|
||||||
// the relative request path of this controller.
|
|
||||||
path := pc.RelPath()
|
|
||||||
return path == relativeRequestPath
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pc *ProfileController) Get() {
|
|
||||||
// requested: "/profile"
|
|
||||||
// so relative path is "/" because of the ProfileController.
|
|
||||||
if pc.match("/") {
|
|
||||||
|
|
||||||
// views/profile/index.html
|
|
||||||
pc.tmpl("index.html")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// requested: "/profile/browse"
|
|
||||||
// so relative path is "/browse".
|
|
||||||
if pc.match("/browse") {
|
|
||||||
pc.Path = "/profile"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// requested: "/profile/me"
|
|
||||||
// so the relative path is "/me"
|
|
||||||
if pc.match("/me") {
|
|
||||||
|
|
||||||
// views/profile/me.html
|
|
||||||
pc.tmpl("me.html")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// requested: "/profile/$ID"
|
|
||||||
// so the relative path is "/$ID"
|
|
||||||
id, _ := pc.Params.GetInt64("id")
|
|
||||||
|
|
||||||
user, found := pc.DB.GetUserByID(id)
|
|
||||||
if !found {
|
|
||||||
pc.Status = iris.StatusNotFound
|
|
||||||
|
|
||||||
// views/profile/notfound.html
|
|
||||||
pc.tmpl("notfound.html")
|
|
||||||
pc.Data["ID"] = id
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// views/profile/profile.html
|
|
||||||
pc.tmpl("profile.html")
|
|
||||||
pc.User = user
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Want to learn more about these functions? Go to the [mvc/controller_test.go](mvc/controller_test.go) file and scroll to the bottom!
|
Want to learn more about these functions? Go to the [mvc/controller_test.go](mvc/controller_test.go) file and scroll to the bottom!
|
||||||
|
|
||||||
|
@ -769,7 +708,7 @@ and it adds its logic to its `BeginRequest`, [here](https://github.com/kataras/i
|
||||||
|
|
||||||
Read access to the current route via the `Route` field.
|
Read access to the current route via the `Route` field.
|
||||||
|
|
||||||
**Using Iris MVC for code reuse**
|
**Using Iris MVC for code reuse**
|
||||||
|
|
||||||
By creating components that are independent of one another, developers are able to reuse components quickly and easily in other applications. The same (or similar) view for one application can be refactored for another application with different data because the view is simply handling how the data is being displayed to the user.
|
By creating components that are independent of one another, developers are able to reuse components quickly and easily in other applications. The same (or similar) view for one application can be refactored for another application with different data because the view is simply handling how the data is being displayed to the user.
|
||||||
|
|
||||||
|
@ -778,9 +717,7 @@ If you're new to back-end web development read about the MVC architectural patte
|
||||||
|
|
||||||
Follow the examples below,
|
Follow the examples below,
|
||||||
|
|
||||||
- [Hello world](_examples/mvc/hello-world/main.go)
|
https://github.com/kataras/iris/tree/master/_examples/#mvc
|
||||||
- [Session Controller](_examples/mvc/session-controller/main.go)
|
|
||||||
- [A simple but featured Controller with model and views](_examples/mvc/controller-with-model-and-view).
|
|
||||||
|
|
||||||
### Bugs
|
### Bugs
|
||||||
|
|
||||||
|
|
|
@ -712,7 +712,7 @@ func (m Movie) IsValid() bool {
|
||||||
```
|
```
|
||||||
|
|
||||||
Iris is able to convert any custom data Structure into an HTTP Response Dispatcher,
|
Iris is able to convert any custom data Structure into an HTTP Response Dispatcher,
|
||||||
so theoritically, something like the following is permitted if it's really necessary;
|
so theoretically, something like the following is permitted if it's really necessary;
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Dispatch completes the `kataras/iris/mvc#Result` interface.
|
// Dispatch completes the `kataras/iris/mvc#Result` interface.
|
||||||
|
|
|
@ -183,15 +183,18 @@ func(c *ExampleController) Get() string |
|
||||||
(string, string) |
|
(string, string) |
|
||||||
(string, int) |
|
(string, int) |
|
||||||
int |
|
int |
|
||||||
(int, string |
|
(int, string) |
|
||||||
(string, error) |
|
(string, error) |
|
||||||
|
bool |
|
||||||
|
(any, bool) |
|
||||||
|
(bool, any) |
|
||||||
error |
|
error |
|
||||||
(int, error) |
|
(int, error) |
|
||||||
(customStruct, error) |
|
(customStruct, error) |
|
||||||
customStruct |
|
customStruct |
|
||||||
(customStruct, int) |
|
(customStruct, int) |
|
||||||
(customStruct, string) |
|
(customStruct, string) |
|
||||||
mvc.Result or (mvc.Result, error)
|
mvc.Result or (mvc.Result, error) and so on...
|
||||||
```
|
```
|
||||||
|
|
||||||
where [mvc.Result](https://github.com/kataras/iris/blob/master/mvc/method_result.go) is an interface which contains only that function: `Dispatch(ctx iris.Context)`.
|
where [mvc.Result](https://github.com/kataras/iris/blob/master/mvc/method_result.go) is an interface which contains only that function: `Dispatch(ctx iris.Context)`.
|
||||||
|
@ -204,13 +207,20 @@ If you're new to back-end web development read about the MVC architectural patte
|
||||||
|
|
||||||
Follow the examples below,
|
Follow the examples below,
|
||||||
|
|
||||||
|
- [Hello world](mvc/hello-world/main.go) **UPDATED**
|
||||||
|
- [Session Controller](mvc/session-controller/main.go) **UPDATED**
|
||||||
- [Overview - Plus Repository and Service layers](mvc/overview) **NEW**
|
- [Overview - Plus Repository and Service layers](mvc/overview) **NEW**
|
||||||
- [Login showcase - Plus Repository and Service layers](mvc/login) **NEW**
|
- [Login showcase - Plus Repository and Service layers](mvc/login) **NEW**
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
- [Hello world](mvc/hello-world/main.go)
|
Why updated?
|
||||||
- [Session Controller](mvc/session-controller/main.go)
|
Old method works, as promised no breaking changes.
|
||||||
- [A simple but featured Controller with model and views](mvc/controller-with-model-and-view)
|
But mvc.C as controller marker and mvc.Result on method functions return value
|
||||||
|
is more lightweight and faster than `mvc.Controller` because `mvc.Controller` initializes
|
||||||
|
some fields like `Data, Path`... and Data is a map even if not used, at the opossite hand
|
||||||
|
`mvc.C` just initializes the context `Ctx` field, the dev has all the `mvc.Controller`'s features
|
||||||
|
by the `mvc.Result` built'n types like `mvc.Response` and `mvc.View` PLUS she/he can
|
||||||
|
convert any custom type into a response dispatcher by implementing the `mvc.Result` interface.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
### Subdomains
|
### Subdomains
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
app := iris.New()
|
|
||||||
app.RegisterView(iris.HTML("./views", ".html"))
|
|
||||||
|
|
||||||
// when we have a path separated by spaces
|
|
||||||
// then the Controller is registered to all of them one by one.
|
|
||||||
//
|
|
||||||
// myDB is binded to the controller's `*DB` field: use only structs and pointers.
|
|
||||||
app.Controller("/profile /profile/browse /profile/{id:int} /profile/me",
|
|
||||||
new(ProfileController), myDB) // IMPORTANT
|
|
||||||
|
|
||||||
app.Run(iris.Addr(":8080"))
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserModel our example model which will render on the template.
|
|
||||||
type UserModel struct {
|
|
||||||
ID int64
|
|
||||||
Username string
|
|
||||||
}
|
|
||||||
|
|
||||||
// DB is our example database.
|
|
||||||
type DB struct {
|
|
||||||
usersTable map[int64]UserModel
|
|
||||||
mu sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUserByID imaginary database lookup based on user id.
|
|
||||||
func (db *DB) GetUserByID(id int64) (u UserModel, found bool) {
|
|
||||||
db.mu.RLock()
|
|
||||||
u, found = db.usersTable[id]
|
|
||||||
db.mu.RUnlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var myDB = &DB{
|
|
||||||
usersTable: map[int64]UserModel{
|
|
||||||
1: {1, "kataras"},
|
|
||||||
2: {2, "makis"},
|
|
||||||
42: {42, "jdoe"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProfileController our example user controller which controls
|
|
||||||
// the paths of "/profile" "/profile/{id:int}" and "/profile/me".
|
|
||||||
type ProfileController struct {
|
|
||||||
iris.Controller // IMPORTANT
|
|
||||||
|
|
||||||
User UserModel `iris:"model"`
|
|
||||||
// we will bind it but you can also tag it with`iris:"persistence"`
|
|
||||||
// and init the controller with manual &PorifleController{DB: myDB}.
|
|
||||||
DB *DB
|
|
||||||
}
|
|
||||||
|
|
||||||
// These two functions are totally optional, of course, don't use them if you
|
|
||||||
// don't need such as a coupled behavior.
|
|
||||||
func (pc *ProfileController) tmpl(relativeTmplPath string) {
|
|
||||||
// the relative templates directory of this controller.
|
|
||||||
views := pc.RelTmpl()
|
|
||||||
pc.Tmpl = views + relativeTmplPath
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pc *ProfileController) match(relativeRequestPath string) bool {
|
|
||||||
// the relative request path based on this controller's name.
|
|
||||||
path := pc.RelPath()
|
|
||||||
return path == relativeRequestPath
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get method handles all "GET" HTTP Method requests of the controller's paths.
|
|
||||||
func (pc *ProfileController) Get() { // IMPORTANT
|
|
||||||
// requested: "/profile"
|
|
||||||
if pc.match("/") {
|
|
||||||
pc.tmpl("index.html")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// requested: "/profile/browse"
|
|
||||||
// this exists only to proof the concept of changing the path:
|
|
||||||
// it will result to a redirection.
|
|
||||||
if pc.match("/browse") {
|
|
||||||
pc.Path = "/profile"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// requested: "/profile/me"
|
|
||||||
if pc.match("/me") {
|
|
||||||
pc.tmpl("me.html")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// requested: "/profile/$ID"
|
|
||||||
id, _ := pc.Params.GetInt64("id")
|
|
||||||
|
|
||||||
user, found := pc.DB.GetUserByID(id)
|
|
||||||
if !found {
|
|
||||||
pc.Status = iris.StatusNotFound
|
|
||||||
pc.tmpl("notfound.html")
|
|
||||||
pc.Data["ID"] = id
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pc.tmpl("profile.html")
|
|
||||||
pc.User = user
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>Profile Browser</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<p>
|
|
||||||
This is the main page of the <b>/profile</b> path, we'd use that to browser profiles.
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,13 +0,0 @@
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>My Profile</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<p>
|
|
||||||
This is the current's user imaginary profile space.
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,13 +0,0 @@
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>Not Found</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<p>
|
|
||||||
User with <b>{{.ID}}</b> doesn't exist!</b>
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,13 +0,0 @@
|
||||||
<html>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title>Profile of {{.User.Username}}</title>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<p>
|
|
||||||
This is the profile of a user with ID: <b>{{.User.ID}}</b> and Username: <b>{{.User.Username}}</b>
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -55,32 +55,54 @@ func main() {
|
||||||
type ExampleController struct {
|
type ExampleController struct {
|
||||||
// if you build with go1.8 you have to use the mvc package always,
|
// if you build with go1.8 you have to use the mvc package always,
|
||||||
// otherwise
|
// otherwise
|
||||||
// you can simply use `iris.Controller`.
|
// you can, optionally
|
||||||
mvc.Controller
|
// use the type alias `iris.C`,
|
||||||
|
// same for
|
||||||
|
// context.Context -> iris.Context,
|
||||||
|
// mvc.Result -> iris.Result,
|
||||||
|
// mvc.Response -> iris.Response,
|
||||||
|
// mvc.View -> iris.View
|
||||||
|
mvc.C
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get serves
|
// Get serves
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080
|
// Resource: http://localhost:8080
|
||||||
func (c *ExampleController) Get() {
|
func (c *ExampleController) Get() mvc.Result {
|
||||||
c.ContentType = "text/html"
|
return mvc.Response{
|
||||||
c.Text = "<h1>Welcome!</h1>"
|
ContentType: "text/html",
|
||||||
|
Text: "<h1>Welcome</h1>",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPing serves
|
// GetPing serves
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080/ping
|
// Resource: http://localhost:8080/ping
|
||||||
func (c *ExampleController) GetPing() {
|
func (c *ExampleController) GetPing() string {
|
||||||
c.Text = "pong"
|
return "pong"
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHello serves
|
// GetHello serves
|
||||||
// Method: GET
|
// Method: GET
|
||||||
// Resource: http://localhost:8080/hello
|
// Resource: http://localhost:8080/hello
|
||||||
func (c *ExampleController) GetHello() {
|
func (c *ExampleController) GetHello() interface{} {
|
||||||
c.Ctx.JSON(iris.Map{"message": "Hello Iris!"})
|
return map[string]string{"message": "Hello Iris!"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserBy serves
|
||||||
|
// Method: GET
|
||||||
|
// Resource: http://localhost:8080/user/{username:string}
|
||||||
|
// By is a reserved "keyword" to tell the framework that you're going to
|
||||||
|
// bind path parameters in the function's input arguments, and it also
|
||||||
|
// helps to have "Get" and "GetBy" in the same controller.
|
||||||
|
//
|
||||||
|
// func (c *ExampleController) GetUserBy(username string) mvc.Result {
|
||||||
|
// return mvc.View{
|
||||||
|
// Name: "user/username.html",
|
||||||
|
// Data: username,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
/* Can use more than one, the factory will make sure
|
/* Can use more than one, the factory will make sure
|
||||||
that the correct http methods are being registered for each route
|
that the correct http methods are being registered for each route
|
||||||
for this controller, uncomment these if you want:
|
for this controller, uncomment these if you want:
|
||||||
|
|
|
@ -22,7 +22,7 @@ func (m User) IsValid() bool {
|
||||||
```
|
```
|
||||||
|
|
||||||
Iris is able to convert any custom data Structure into an HTTP Response Dispatcher,
|
Iris is able to convert any custom data Structure into an HTTP Response Dispatcher,
|
||||||
so theoritically, something like the following is permitted if it's really necessary;
|
so theoretically, something like the following is permitted if it's really necessary;
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Dispatch completes the `kataras/iris/mvc#Result` interface.
|
// Dispatch completes the `kataras/iris/mvc#Result` interface.
|
||||||
|
|
|
@ -22,7 +22,7 @@ func (m Movie) IsValid() bool {
|
||||||
```
|
```
|
||||||
|
|
||||||
Iris is able to convert any custom data Structure into an HTTP Response Dispatcher,
|
Iris is able to convert any custom data Structure into an HTTP Response Dispatcher,
|
||||||
so theoritically, something like the following is permitted if it's really necessary;
|
so theoretically, something like the following is permitted if it's really necessary;
|
||||||
|
|
||||||
```go
|
```go
|
||||||
// Dispatch completes the `kataras/iris/mvc#Result` interface.
|
// Dispatch completes the `kataras/iris/mvc#Result` interface.
|
||||||
|
|
|
@ -1,40 +1,78 @@
|
||||||
|
// +build go1.9
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/kataras/iris"
|
"github.com/kataras/iris"
|
||||||
|
|
||||||
"github.com/kataras/iris/sessions"
|
"github.com/kataras/iris/sessions"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// VisitController handles the root route.
|
||||||
type VisitController struct {
|
type VisitController struct {
|
||||||
iris.SessionController
|
iris.C
|
||||||
|
|
||||||
|
// the sessions manager, we need that to set `Session`.
|
||||||
|
// It's binded from `app.Controller`.
|
||||||
|
Manager *sessions.Sessions
|
||||||
|
// the current request session,
|
||||||
|
// its initialization happens at the `BeginRequest`.
|
||||||
|
Session *sessions.Session
|
||||||
|
|
||||||
|
// A time.time which is binded from the `app.Controller`,
|
||||||
|
// order of binded fields doesn't matter.
|
||||||
StartTime time.Time
|
StartTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *VisitController) Get() {
|
// BeginRequest is executed for each Get, Post, Put requests,
|
||||||
|
// can be used to share context, common data
|
||||||
|
// or to cancel the request via `ctx.StopExecution()`.
|
||||||
|
func (c *VisitController) BeginRequest(ctx iris.Context) {
|
||||||
|
// always call the embedded `BeginRequest` before everything else.
|
||||||
|
c.C.BeginRequest(ctx)
|
||||||
|
|
||||||
|
if c.Manager == nil {
|
||||||
|
ctx.Application().Logger().Errorf(`VisitController: sessions manager is nil, you should bind it`)
|
||||||
|
// dont run the main method handler and any "done" handlers.
|
||||||
|
ctx.StopExecution()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the `c.Session` we will use that in our Get method.
|
||||||
|
c.Session = c.Manager.Start(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get handles
|
||||||
|
// Method: GET
|
||||||
|
// Path: http://localhost:8080
|
||||||
|
func (c *VisitController) Get() string {
|
||||||
// get the visits, before calcuate this new one.
|
// get the visits, before calcuate this new one.
|
||||||
visits, _ := u.Session.GetIntDefault("visits", 0)
|
visits, _ := c.Session.GetIntDefault("visits", 0)
|
||||||
|
|
||||||
// increment the visits and store to the session.
|
// increment the visits and store to the session.
|
||||||
visits++
|
visits++
|
||||||
u.Session.Set("visits", visits)
|
c.Session.Set("visits", visits)
|
||||||
|
|
||||||
// write the current, updated visits
|
// write the current, updated visits.
|
||||||
u.Ctx.Writef("%d visit from my current session in %0.1f seconds of server's up-time",
|
since := time.Now().Sub(c.StartTime).Seconds()
|
||||||
visits, time.Now().Sub(u.StartTime).Seconds())
|
return fmt.Sprintf("%d visit from my current session in %0.1f seconds of server's up-time",
|
||||||
|
visits, since)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
var (
|
||||||
mySessionManager := sessions.New(sessions.Config{Cookie: "mysession_cookie_name"})
|
manager = sessions.New(sessions.Config{Cookie: "mysession_cookie_name"})
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
app := iris.New()
|
app := iris.New()
|
||||||
|
|
||||||
// bind our session manager, which is required, to the `VisitController.SessionManager.Manager`
|
// bind our session manager, which is required, to the `VisitController.Manager`
|
||||||
// and the time.Now() to the `VisitController.StartTime`.
|
// and the time.Now() to the `VisitController.StartTime`.
|
||||||
app.Controller("/", new(VisitController), mySessionManager, time.Now())
|
app.Controller("/", new(VisitController),
|
||||||
|
manager,
|
||||||
|
time.Now())
|
||||||
|
|
||||||
// 1. open the browser (no in private mode)
|
// 1. open the browser (no in private mode)
|
||||||
// 2. navigate to http://localhost:8080
|
// 2. navigate to http://localhost:8080
|
||||||
|
|
21
doc.go
21
doc.go
|
@ -961,10 +961,15 @@ The example below is not intended to be used in production but it's a good showc
|
||||||
|
|
||||||
// MoviesController is our /movies controller.
|
// MoviesController is our /movies controller.
|
||||||
type MoviesController struct {
|
type MoviesController struct {
|
||||||
// mvc.C is just a lightweight lightweight alternative
|
// if you build with go1.8 you have to use the mvc package always,
|
||||||
// to the "mvc.Controller" controller type,
|
// otherwise
|
||||||
// use it when you don't need mvc.Controller's fields
|
// you can, optionally
|
||||||
// (you don't need those fields when you return values from the method functions).
|
// use the type alias `iris.C`,
|
||||||
|
// same for
|
||||||
|
// context.Context -> iris.Context,
|
||||||
|
// mvc.Result -> iris.Result,
|
||||||
|
// mvc.Response -> iris.Response,
|
||||||
|
// mvc.View -> iris.View
|
||||||
mvc.C
|
mvc.C
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,13 +1039,7 @@ different data because the view is simply handling how the data is being display
|
||||||
If you're new to back-end web development read about the MVC architectural pattern first,
|
If you're new to back-end web development read about the MVC architectural pattern first,
|
||||||
a good start is that wikipedia article: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller.
|
a good start is that wikipedia article: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller.
|
||||||
|
|
||||||
Follow the examples below,
|
Follow the examples at: https://github.com/kataras/iris/tree/master/_examples/#mvc
|
||||||
|
|
||||||
- Hello world: https://github.com/kataras/iris/blob/master/_examples/mvc/hello-world/main.go
|
|
||||||
|
|
||||||
- Session Controller usage: https://github.com/kataras/iris/blob/master/_examples/mvc/session-controller/main.go
|
|
||||||
|
|
||||||
- A simple but featured Controller with model and views: https://github.com/kataras/iris/tree/master/_examples/mvc/controller-with-model-and-view
|
|
||||||
|
|
||||||
|
|
||||||
Parameterized Path
|
Parameterized Path
|
||||||
|
|
|
@ -59,7 +59,7 @@ var (
|
||||||
// a new Controller type.
|
// a new Controller type.
|
||||||
// Controller looks the whole flow as one handler, so `ctx.Next`
|
// Controller looks the whole flow as one handler, so `ctx.Next`
|
||||||
// inside `BeginRequest` is not be respected.
|
// inside `BeginRequest` is not be respected.
|
||||||
// Alternative way to check if a middleware was procceed succesfully
|
// Alternative way to check if a middleware was procceed successfully
|
||||||
// and called its `ctx.Next` is the `ctx.Proceed(handler) bool`.
|
// and called its `ctx.Next` is the `ctx.Proceed(handler) bool`.
|
||||||
// You have to navigate to the `context/context#Proceed` function's documentation.
|
// You have to navigate to the `context/context#Proceed` function's documentation.
|
||||||
type BaseController interface {
|
type BaseController interface {
|
||||||
|
|
|
@ -171,7 +171,7 @@ func DispatchFuncResult(ctx context.Context, values []reflect.Value) {
|
||||||
found = b
|
found = b
|
||||||
if !found {
|
if !found {
|
||||||
// skip everything, we don't care about other return values,
|
// skip everything, we don't care about other return values,
|
||||||
// this boolean is the heighest in order.
|
// this boolean is the higher in order.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -37,7 +37,7 @@ var DefaultViewExt = ".html"
|
||||||
|
|
||||||
func ensureExt(s string) string {
|
func ensureExt(s string) string {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
return "index.html"
|
return "index" + DefaultViewExt
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.IndexByte(s, dotB) < 1 {
|
if strings.IndexByte(s, dotB) < 1 {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user