Так выглядит протокол Parameter
public protocol Parameter {
associatedtype ResolvedParameter
static var routingSlug: String { get }
static func resolveParameter(_ parameter: String, on container: Container) throws -> ResolvedParameter
}
когда вы что-либо соответствуете Parameter
, вы должны реализовать эту функцию
static func resolveParameter(_ parameter: String, on container: Container) throws -> ResolvedParameter
который должен анализировать строковый параметр из URL и возвращать в результате некоторый объект. И поскольку Parameter
является общим, вы можете вернуть любой тип, который хотите.
Давайте напишем расширение, чтобы соответствовать Date
до Parameter
extension Date: Parameter {
public static func resolveParameter(_ parameter: String, on container: Container) throws -> Date {
guard let timeIntervalSince1970 = TimeInterval(parameter) else {
throw Abort(.notAcceptable, reason: "Unable to parse \"\(parameter)\" parameter")
}
return Date(timeIntervalSince1970: timeIntervalSince1970)
}
}
Метод Parameter
анализирует параметр String
из URL и возвращает Date
, но вы также можете вернуть что-то еще, например. TimeInterval
, так как Parameter
является общим протоколом
extension Date: Parameter {
public static func resolveParameter(_ parameter: String, on container: Container) throws -> TimeInterval {
guard let timeIntervalSince1970 = TimeInterval(parameter) else {
throw Abort(.notAcceptable, reason: "Unable to parse \"\(parameter)\" parameter")
}
return timeIntervalSince1970
}
}
Когда вы согласовываете свою модель Fluent с Parameter
, в ее расширениях уже есть реализация протокола Parameter
, поэтому вам не следует объявлять функцию resolveParameter
вручную.
Давайте посмотрим, как это работает, если вы объявите метод resolveParameter
вручную, например, в User
модель
extension User {
public static func resolveParameter(_ parameter: String, on container: Container) throws -> Future<User> {
// e.g. User's primary key is UUID
guard let id = UUID(parameter) else {
throw Abort(.notAcceptable, reason: "Unable to parse \"\(parameter)\" into UUID")
}
// getting database connection from pool
return container.requestPooledConnection(to: .psql).flatMap { conn in
// querying user by provided primary key
return User.query(on: conn)
.filter(\.id == id)
.first()
.unwrap(or: Abort(.notFound, reason: "Unable to find user by provided primary key"))
.always {
// will release connection in any case
try? container.releasePooledConnection(conn, to: .psql)
}
}
}
}
Итак, как видите, вы можете реализовать resolveParameter
, чтобы вернуть все, что захотите.
person
imike
schedule
13.07.2019
Parameter
протокол. Когда вы согласовываете свою модель базы данных сParameter
, вы можете вернуть Future с этим элементом из базы данных. Поэтому в своих запросах вы можете получить объект из БД просто по его ID в параметрах URL. - person imike   schedule 13.07.2019User
модель в вашем текущем проекте Vapor. Если это так, то просто добавьтеextension User: Parameter {}
, чтобы согласовать эту модель сParameter
, а затем попробуйте использовать ее в какой-либо конечной точке в вашем контроллере, напримерrouter.get("test", User.parameter) { try $0.parameters.next(User.self) }
, затем попробуйте вызвать ее следующим образом: localhost:8080/test/‹USER_ID› - person imike   schedule 13.07.2019imike#3049
:) - person imike   schedule 13.07.2019