Skip to content

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.