1
0
mirror of https://github.com/kataras/iris.git synced 2025-12-21 20:07:04 +00:00

add a new 'overview' MVC example

Former-commit-id: f73cbf6010595c639f6c5b5119e2ec41bc9802a5
This commit is contained in:
Gerasimos (Makis) Maropoulos
2020-06-21 00:12:07 +03:00
parent 45c6bce15f
commit d55bb34766
29 changed files with 361 additions and 148 deletions

View File

@@ -0,0 +1,58 @@
// file: web/controllers/hello_controller.go
package controllers
import (
"errors"
"github.com/kataras/iris/v12/mvc"
)
// HelloController is our sample controller
// it handles GET: /hello and GET: /hello/{name}
type HelloController struct{}
var helloView = mvc.View{
Name: "hello/index.html",
Data: map[string]interface{}{
"Title": "Hello Page",
"MyMessage": "Welcome to my awesome website",
},
}
// Get will return a predefined view with bind data.
//
// `mvc.Result` is just an interface with a `Dispatch` function.
// `mvc.Response` and `mvc.View` are the builtin result type dispatchers
// you can even create custom response dispatchers by
// implementing the `github.com/kataras/iris/hero#Result` interface.
func (c *HelloController) Get() mvc.Result {
return helloView
}
// you can define a standard error in order to re-use anywhere in your app.
var errBadName = errors.New("bad name")
// you can just return it as error or even better
// wrap this error with an mvc.Response to make it an mvc.Result compatible type.
var badName = mvc.Response{Err: errBadName, Code: 400}
// GetBy returns a "Hello {name}" response.
// Demos:
// curl -i http://localhost:8080/hello/iris
// curl -i http://localhost:8080/hello/anything
func (c *HelloController) GetBy(name string) mvc.Result {
if name != "iris" {
return badName
// or
// GetBy(name string) (mvc.Result, error) {
// return nil, errBadName
// }
}
// return mvc.Response{Text: "Hello " + name} OR:
return mvc.View{
Name: "hello/name.html",
Data: name,
}
}

View File

@@ -0,0 +1,77 @@
// file: web/controllers/movie_controller.go
package controllers
import (
"errors"
"github.com/kataras/iris/v12/_examples/mvc/repository/datamodels"
"github.com/kataras/iris/v12/_examples/mvc/repository/services"
"github.com/kataras/iris/v12"
)
// MovieController is our /movies controller.
type MovieController struct {
// Our MovieService, it's an interface which
// is binded from the main application.
Service services.MovieService
}
// Get returns list of the movies.
// Demo:
// curl -i http://localhost:8080/movies
//
// The correct way if you have sensitive data:
// func (c *MovieController) Get() (results []viewmodels.Movie) {
// data := c.Service.GetAll()
//
// for _, movie := range data {
// results = append(results, viewmodels.Movie{movie})
// }
// return
// }
// otherwise just return the datamodels.
func (c *MovieController) Get() (results []datamodels.Movie) {
return c.Service.GetAll()
}
// GetBy returns a movie.
// Demo:
// curl -i http://localhost:8080/movies/1
func (c *MovieController) GetBy(id int64) (movie datamodels.Movie, found bool) {
return c.Service.GetByID(id) // it will throw 404 if not found.
}
// PutBy updates a movie.
// Demo:
// curl -i -X PUT -F "genre=Thriller" -F "poster=@/Users/kataras/Downloads/out.gif" http://localhost:8080/movies/1
func (c *MovieController) PutBy(ctx iris.Context, id int64) (datamodels.Movie, error) {
// get the request data for poster and genre
file, info, err := ctx.FormFile("poster")
if err != nil {
return datamodels.Movie{}, errors.New("failed due form file 'poster' missing")
}
// we don't need the file so close it now.
file.Close()
// imagine that is the url of the uploaded file...
poster := info.Filename
genre := ctx.FormValue("genre")
return c.Service.UpdatePosterAndGenreByID(id, poster, genre)
}
// DeleteBy deletes a movie.
// Demo:
// curl -i -X DELETE -u admin:password http://localhost:8080/movies/1
func (c *MovieController) DeleteBy(id int64) interface{} {
wasDel := c.Service.DeleteByID(id)
if wasDel {
// return the deleted movie's ID
return iris.Map{"deleted": id}
}
// right here we can see that a method function can return any of those two types(map or int),
// we don't have to specify the return type to a specific type.
return iris.StatusBadRequest
}

View File

@@ -0,0 +1,12 @@
// file: web/middleware/basicauth.go
package middleware
import "github.com/kataras/iris/v12/middleware/basicauth"
// BasicAuth middleware sample.
var BasicAuth = basicauth.New(basicauth.Config{
Users: map[string]string{
"admin": "password",
},
})

View File

@@ -0,0 +1,56 @@
# View Models
There should be the view models, the structure that the client will be able to see.
Example:
```go
import (
"github.com/kataras/iris/v12/_examples/mvc/repository/datamodels"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/context"
)
type Movie struct {
datamodels.Movie
}
func (m Movie) IsValid() bool {
/* do some checks and return true if it's valid... */
return m.ID > 0
}
```
Iris is able to convert any custom data Structure into an HTTP Response Dispatcher,
so theoretically, something like the following is permitted if it's really necessary;
```go
// Dispatch completes the `kataras/iris/mvc#Result` interface.
// Sends a `Movie` as a controlled http response.
// If its ID is zero or less then it returns a 404 not found error
// else it returns its json representation,
// (just like the controller's functions do for custom types by default).
//
// Don't overdo it, the application's logic should not be here.
// It's just one more step of validation before the response,
// simple checks can be added here.
//
// It's just a showcase,
// imagine the potentials this feature gives when designing a bigger application.
//
// This is called where the return value from a controller's method functions
// is type of `Movie`.
// For example the `controllers/movie_controller.go#GetBy`.
func (m Movie) Dispatch(ctx iris.Context) {
if !m.IsValid() {
ctx.NotFound()
return
}
ctx.JSON(m, context.JSON{Indent: " "})
}
```
However, we will use the "datamodels" as the only one models package because
Movie structure doesn't contain any sensitive data, clients are able to see all of its fields
and we don't need any extra functionality or validation inside it.

View File

@@ -0,0 +1,12 @@
<!-- file: web/views/hello/index.html -->
<html>
<head>
<title>{{.Title}} - My App</title>
</head>
<body>
<p>{{.MyMessage}}</p>
</body>
</html>

View File

@@ -0,0 +1,12 @@
<!-- file: web/views/hello/name.html -->
<html>
<head>
<title>{{.}}' Portfolio - My App</title>
</head>
<body>
<h1>Hello {{.}}</h1>
</body>
</html>