蒸气机制中的request.parameters.next如何工作?

时间:2019-07-13 07:35:55

标签: vapor

在使用Vapor构建API时,请始终使用一种方法来获取对象,

request.parameters.next(type.self)

似乎是一种提取url参数的方法,为什么它从数据库返回结果?从框架的源代码中找不到任何线索。我如何找到答案?谢谢。

1 个答案:

答案 0 :(得分:3)

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的方法从URL解析String参数并返回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来返回所需的任何内容。