如何使用 parent id 来放置 children 的数据?
How can I use the parent id to put the children's data?
final class InformationController{
func create (_ req: Request) throws -> EventLoopFuture<Pers>{
let perinfo=try req.content.decode(Pers.self)
return perinfo.save(on: req.db).map {perinfo}
}
func putpers (_ req: Request) throws -> EventLoopFuture<HTTPStatus> {
let information = try req.content.decode(Pers.self)
return Pers.find(information.$user.id, on: req.db)
.unwrap(or: Abort(.notFound))
.flatMap{
[=12=].name=information.name
[=12=].account=information.account
[=12=].picture=information.picture
[=12=].age=information.age
[=12=].birth=information.birth
[=12=].city=information.city
[=12=].hobby=information.hobby
return [=12=].update(on: req.db).transform(to: .ok)
}
}
}
final class UserController{
func signup (_ req: Request) throws -> EventLoopFuture<User>{
try User.Create.validate(content: req)
// 從request body中decode出User.Create
let newUser = try req.content.decode(User.Create.self)
// 先檢查密碼是否==確認密碼
guard newUser.password == newUser.confirmPassword else {
throw Abort(.badRequest, reason: "Passwords did not match")
}
// 將User.Create 轉成 User
let user = try User(account: newUser.account, password: Bcrypt.hash(newUser.password))
// 儲存User並回傳
return user.save(on: req.db).map { user }
}
}
这是我的控制器。我将 User
用作 parent。而 Pers
作为 children。
但是当我使用邮递员做 api 时。它一直告诉我这个:
因为我认为使用 2 个 ID 来执行操作有点奇怪。我将关系设为 one to many
。因为我在范围
中找不到 Child
路线:
import Fluent
import Vapor
func routes(_ app: Application) throws {
let userController = UserController()
let informationController=InformationController()
let passwordProtected = app.grouped(User.authenticator(),User.guardMiddleware())
let tokenProtected = app.grouped(UserToken.authenticator(),UserToken.guardMiddleware())
//修改密碼
app.put("user",":userId", use:userController.update)//
//第一次上傳個人資料
app.post("information", use:informationController.create)//
//更新個人資料
app.put("information", use:informationController.new)
//註冊
app.post("signup", use:userController.signup)//ok
//登陸
passwordProtected.post("login",use: userController.login)//
//登陸後收到個人資料
tokenProtected.get("getperinfo",use: userController.getperinfo)//
//收到他人資料
app.get("otherperinfo",":userId",use:informationController.otherperinfo)//
//登出
app.delete("logout",":user_tokensId", use: userController.logout)//
}
parent 型号:
import Foundation
import Fluent
import Vapor
import FluentPostgresDriver
final class User:Model,Content{
static let schema = "user"
@ID(key: .id)
var id:UUID?
@Field(key:"帳號")
var account:String
@Field(key: "密碼")
var password:String
@Children(for: \.$user)
var perinfo: [Pers]
init() {}
init(id: UUID?=nil, account:String, password:String){
self.id=id
self.account=account
self.password=password
}
}
children 型号:
import Foundation
import Fluent
import Vapor
import FluentPostgresDriver
final class Pers:Model,Content{
static let schema = "pers"
@ID(key: .id)
var id:UUID?
@Field(key: "姓名")
var name: String
@Field(key: "IG帳號")
var account: String
@Field(key: "頭像")
var picture: String
@Field(key: "年紀")
var age: String
@Field(key: "生日")
var birth: String
@Field(key: "居住城市")
var city: String
@Field(key: "興趣")
var hobby : String
@Parent(key: "user_id")
var user: User
init(){}
init(id:UUID?=nil, name:String, account:String, picture:String ,age:String, birth:String, city:String, hobby:String, userId:UUID){
self.id=id
self.name=name
self.account=account
self.picture=picture
self.age=age
self.birth=birth
self.city=city
self.hobby=hobby
self.$user.id=userId
}
}
您遇到的问题是您正在向 API 发送一个平面 JSON 对象,我敢打赌试图将其解码为具有父子关系的模型。 Fluent 的 属性 包装器可以轻松显示关系,但它也可以以其他方式工作。
您有两个选择:
更改您发送的 JSON 以符合 Vapor 的预期,因此它看起来像:
{
"name": "dog",
"account": "222",
// ...
"user": {
"id": "<USER_ID>"
}
}
或者您可以创建一个 DTO 来匹配您希望客户端发送给您的数据,对其进行解码,将其转换为 Pers
并保存。有关示例,请参见 Vapor TIL repo。
final class InformationController{
func create (_ req: Request) throws -> EventLoopFuture<Pers>{
let perinfo=try req.content.decode(Pers.self)
return perinfo.save(on: req.db).map {perinfo}
}
func putpers (_ req: Request) throws -> EventLoopFuture<HTTPStatus> {
let information = try req.content.decode(Pers.self)
return Pers.find(information.$user.id, on: req.db)
.unwrap(or: Abort(.notFound))
.flatMap{
[=12=].name=information.name
[=12=].account=information.account
[=12=].picture=information.picture
[=12=].age=information.age
[=12=].birth=information.birth
[=12=].city=information.city
[=12=].hobby=information.hobby
return [=12=].update(on: req.db).transform(to: .ok)
}
}
}
final class UserController{
func signup (_ req: Request) throws -> EventLoopFuture<User>{
try User.Create.validate(content: req)
// 從request body中decode出User.Create
let newUser = try req.content.decode(User.Create.self)
// 先檢查密碼是否==確認密碼
guard newUser.password == newUser.confirmPassword else {
throw Abort(.badRequest, reason: "Passwords did not match")
}
// 將User.Create 轉成 User
let user = try User(account: newUser.account, password: Bcrypt.hash(newUser.password))
// 儲存User並回傳
return user.save(on: req.db).map { user }
}
}
这是我的控制器。我将 User
用作 parent。而 Pers
作为 children。
但是当我使用邮递员做 api 时。它一直告诉我这个:
one to many
。因为我在范围
Child
路线:
import Fluent
import Vapor
func routes(_ app: Application) throws {
let userController = UserController()
let informationController=InformationController()
let passwordProtected = app.grouped(User.authenticator(),User.guardMiddleware())
let tokenProtected = app.grouped(UserToken.authenticator(),UserToken.guardMiddleware())
//修改密碼
app.put("user",":userId", use:userController.update)//
//第一次上傳個人資料
app.post("information", use:informationController.create)//
//更新個人資料
app.put("information", use:informationController.new)
//註冊
app.post("signup", use:userController.signup)//ok
//登陸
passwordProtected.post("login",use: userController.login)//
//登陸後收到個人資料
tokenProtected.get("getperinfo",use: userController.getperinfo)//
//收到他人資料
app.get("otherperinfo",":userId",use:informationController.otherperinfo)//
//登出
app.delete("logout",":user_tokensId", use: userController.logout)//
}
parent 型号:
import Foundation
import Fluent
import Vapor
import FluentPostgresDriver
final class User:Model,Content{
static let schema = "user"
@ID(key: .id)
var id:UUID?
@Field(key:"帳號")
var account:String
@Field(key: "密碼")
var password:String
@Children(for: \.$user)
var perinfo: [Pers]
init() {}
init(id: UUID?=nil, account:String, password:String){
self.id=id
self.account=account
self.password=password
}
}
children 型号:
import Foundation
import Fluent
import Vapor
import FluentPostgresDriver
final class Pers:Model,Content{
static let schema = "pers"
@ID(key: .id)
var id:UUID?
@Field(key: "姓名")
var name: String
@Field(key: "IG帳號")
var account: String
@Field(key: "頭像")
var picture: String
@Field(key: "年紀")
var age: String
@Field(key: "生日")
var birth: String
@Field(key: "居住城市")
var city: String
@Field(key: "興趣")
var hobby : String
@Parent(key: "user_id")
var user: User
init(){}
init(id:UUID?=nil, name:String, account:String, picture:String ,age:String, birth:String, city:String, hobby:String, userId:UUID){
self.id=id
self.name=name
self.account=account
self.picture=picture
self.age=age
self.birth=birth
self.city=city
self.hobby=hobby
self.$user.id=userId
}
}
您遇到的问题是您正在向 API 发送一个平面 JSON 对象,我敢打赌试图将其解码为具有父子关系的模型。 Fluent 的 属性 包装器可以轻松显示关系,但它也可以以其他方式工作。
您有两个选择:
更改您发送的 JSON 以符合 Vapor 的预期,因此它看起来像:
{
"name": "dog",
"account": "222",
// ...
"user": {
"id": "<USER_ID>"
}
}
或者您可以创建一个 DTO 来匹配您希望客户端发送给您的数据,对其进行解码,将其转换为 Pers
并保存。有关示例,请参见 Vapor TIL repo。