Vapor Controllers

Controllers in Vapor are used to make grouped routes, usually one controller per model, but that is not a requirement.


To be able to send parameters, the controller’s model must conform to Parameter protocol.


extension Season : Parameter{}

I usually put that extension in the model’s .swift file, and not the controllers.


Example controller

import Vapor
import Fluent

struct SeasonsController: RouteCollection {
  
  func boot(router: Router) throws {
    let aRoute = router.grouped("api", "seasons")
    //GET /api/seasons
    aRoute.get(use: getAllHandler)
    //GET /api/seasons/:ID
    aRoute.get(Season.parameter, use: getOneHandler)
  }
  
  func getAllHandler(_ req: Request) throws -> Future<[Season]> {
    return Season.query(on: req).all()
  }
  
  func getOneHandler(_ req: Request) throws -> Future<Season> {
    return try req.parameters.next(Season.self)
  }
}

Getting Children items

Model

In model file Continent.swift


See Parent - Child Relationships in Model Classes.


//Continent ↤⇉ Country
extension Continent {
  var countries: Children<Continent, Country> {
    return children(\.continentID)
  }
}


Route

//GET /api/continents/:continentID/countries
aRoute.get(Continent.parameter, "countries", use: getCountriesHandler)

Method

func getCountriesHandler(_ req: Request) throws -> Future<[Country]> {
    return try req.parameters.next(Continent.self).flatMap(to: [Country].self) { continent in
      return try continent.countries.query(on: req).all()
    }
  }

Getting parent item

Model

In model file Country.swift


See Parent - Child Relationships in Model Classes.


// Country ⇇↦  Continent
extension Country {
  var continent: Parent<Country, Continent> {
    return parent(\.continentID)
  }
}

Route

//GET /api/countries/:ID/continent
aRoute.get(Country.parameter, "continent", use: getContinentHandler)

Method

func getContinentHandler(_ req: Request) throws -> Future<Continent> {
    return try req.parameters.next(Country.self).flatMap(to: Continent.self) { country in
      return try country.continent.get(on: req)
    }
  }

Prev: Parent - Child Relationships in Model Classes

Next: Generic Vapor Controllers


Vapor 3 Tutorial Start



#pub #swift #controller #vapor #model #one-to-many #many-to-one