Skip to content
You are reading the v0.20 documentation. Go to the latest version (v1.0)

The basics

Controllers

Group related handlers in plain structs that receive their dependencies through constructors.

Last updated:

A controller is an ordinary struct whose methods are web.HandlerFuncs. There is no base class and no container: dependencies come in through the constructor.

app/controllers/post.go
type PostController struct {
	log   *slog.Logger
	posts *store.Posts
}

func NewPost(app *vukem.App, posts *store.Posts) *PostController {
	return &PostController{log: app.Log, posts: posts}
}

func (p *PostController) Index(c *web.Ctx) error {
	return c.JSON(http.StatusOK, p.posts.All())
}

func (p *PostController) Show(c *web.Ctx) error {
	id, err := c.ParamInt("post")
	if err != nil {
		return err
	}

	post, ok := p.posts.Find(id)
	if !ok {
		return errs.ErrNotFound
	}

	return c.JSON(http.StatusOK, post)
}

Registering methods#

Method values are handlers, so they register like any function:

Go
posts := controllers.NewPost(app, store)

r.Get("/posts", posts.Index).Name("posts.index")
r.Get("/posts/{post}", posts.Show).Name("posts.show")

Resource controllers#

Implement any subset of Index, Create, Store, Show, Edit, Update and Destroy, then let the router wire the RESTful routes:

Go
r.Resource("posts", posts)        // HTML app: includes create and edit form routes
r.APIResource("products", products) // JSON API: no create/edit

Only implemented methods are routed, detected through one-method interfaces (router.Indexer, router.Storer…). The full table is in Routing.

Go
func (p *PostController) Create(c *web.Ctx) error {
	return c.HTML(http.StatusOK, newPostForm) // GET /posts/create
}

Generator#

Terminal
vukem make:controller Post             # struct, constructor and an Index action
vukem make:controller Post --resource  # the seven resource actions
vukem make:controller Photo --api      # the five JSON actions (no Create/Edit forms)

Files go to app/controllers/<name>_controller.go; a trailing Controller in the name is optional. See CLI.