在上一篇Vapor奇幻之旅(04Routing)中我介紹了Routing的寫法拣宏,作為一個(gè)web應(yīng)用零聚,數(shù)據(jù)庫是必不可少的谆吴,而Fluent則是管理數(shù)據(jù)的一個(gè)抽象層站削,可以支持?jǐn)?shù)據(jù)庫的增刪改查等操作坊萝,默認(rèn)的FluentProvider支持sqlite數(shù)據(jù)庫,也就是說在沒有任何數(shù)據(jù)庫配置的情況下,可以通過Fluent Provider中的內(nèi)存數(shù)據(jù)庫來快速加載SQLite數(shù)據(jù)庫十偶,這樣做的好處是可以輕松的進(jìn)行接口測試菩鲜。
目前Vapor支持的數(shù)據(jù)庫如下:
數(shù)據(jù)庫類型 | Key | Package | Class | 是否來自官方 |
---|---|---|---|---|
Memory | memory | Fluent Provider | Fluent.MemoryDriver | Yes |
SQlite | sqlite | Fluent Provider | Fluent.SQLiteDriver | Yes |
MySQL | mysql | MySQLProvider | MySQLDriver.Driver | Yes |
PostgreSQL | postgresql | PostgreSQLProvider | PostgreSQLDriver.Driver | No |
MongoDB | N/A | MongoProvider | N/A | No |
對于大型數(shù)據(jù)庫官方只有支持到MySQL,稍顯遺憾,開發(fā)團(tuán)隊(duì)最近都在進(jìn)行Vapor 3的開發(fā)惦积,相信不久后就可以有更多的數(shù)據(jù)庫類型支持了接校,而且由于Fluent的抽象的特性,只要有相應(yīng)的驅(qū)動(dòng)狮崩,適配任何數(shù)據(jù)庫我想只是時(shí)間問題蛛勉。
既然是抽象層,我們先不管用啥數(shù)據(jù)庫睦柴,可以先把我們的數(shù)據(jù)模型搭建起來董习。
我想給我的網(wǎng)站加一段名人名言,于是我創(chuàng)建一個(gè)名為Quotes的模型爱只,代碼如下:
import Vapor
import FluentProvider
import HTTP
/// 名人名言
final class Quotes: Model {
// 這個(gè)屬性能讓Fluent存儲(chǔ)額外的信息皿淋,如這個(gè)model的id
let storage = Storage()
//***下面是表中的屬性***
/// 作者
let author: String
/// 內(nèi)容
let content: String
/// 描述
let description: String
/// 數(shù)據(jù)庫中列的名字
struct Keys {
static let id = "id"
static let author = "author"
static let content = "content"
static let description = "description"
}
// MARK: 初始化Fluent
/// 初始化Quotes
required init(row: Row) throws {
author = try row.get(Quotes.Keys.author)
content = try row.get(Quotes.Keys.content)
description = try row.get(Quotes.Keys.description)
}
// 序列化Quotes到數(shù)據(jù)庫
func makeRow() throws -> Row {
var row = Row()
try row.set(Quotes.Keys.author, author)
try row.set(Quotes.Keys.content, content)
try row.set(Quotes.Keys.description, description)
return row
}
}
我們的model有了,下面就該聯(lián)系一下數(shù)據(jù)庫了恬试,F(xiàn)luent 提供了一個(gè)Preparation協(xié)議窝趣,源碼如下:
/// A preparation prepares the database for
/// any task that it may need to perform during runtime.
public protocol Preparation {
/// The prepare method should call any methods
/// it needs on the database to prepare.
static func prepare(_ database: Database) throws
/// The revert method should undo any actions
/// caused by the prepare method.
///
/// If this is impossible, the `PreparationError.revertImpossible`
/// error should be thrown.
static func revert(_ database: Database) throws
}
其中prepare方法是讓數(shù)據(jù)庫做好準(zhǔn)備的方法,比如新建table训柴,而revert方法則是對prepare做的操作進(jìn)行回滾操作哑舒,比如刪除table。
另外幻馁,JSON也是網(wǎng)絡(luò)通訊常用的數(shù)據(jù)格式洗鸵,模型通常也需要轉(zhuǎn)換為JSON串,或者需要解析json串到模型仗嗦。JSON庫為我們提供了JSONConvertible協(xié)議膘滨,demo如下
extension Quotes: JSONConvertible {
convenience init(json: JSON) throws {
self.init(
author: try json.get(Quotes.Keys.author),
content: try json.get(Quotes.Keys.content),
description: try json.get(Quotes.Keys.description)
)
}
func makeJSON() throws -> JSON {
var json = JSON()
try json.set(Quotes.Keys.id, id)
try json.set(Quotes.Keys.author, author)
try json.set(Quotes.Keys.content, content)
try json.set(Quotes.Keys.description, description)
return json
}
}
在寫這個(gè)extension之前,還需要在mode里添加一個(gè)初始化方法:
/// 名人名言
final class Quotes: Model {
...
// MARK: 初始化Fluent
init(author: String, content: String, description: String) {
self.author = author
self.content = content
self.description = description
}
...
}
模型已經(jīng)建好了稀拐,那么作為一個(gè)數(shù)據(jù)庫模型火邓,怎么能少了增刪改查呢,藥藥藥德撬,切克鬧铲咨,增刪改查來一套:
這里我們需要開始寫Controller了,在controller文件夾內(nèi)創(chuàng)建一個(gè)QuotesController.swift的文件:
import Vapor
import FluentProvider
struct QuotesController {
func addRoutes(to drop: Droplet) {
let quots = drop.grouped("api","quots")
}
}
然后在Config+Setup.swift中準(zhǔn)備好新創(chuàng)建的model:
private func setupPreparations() throws {
preparations.append(Quotes.self)
}
接下來在創(chuàng)建一個(gè)Routers+Quotes.swift的文件并添加QuotesController的routs.
Routers+Quotes.swift:
import Vapor
extension Droplet {
func setupQuotes() {
let quotsController = QuotesController()
quotsController.addRoutes(to: self)
}
}
最后在Droplet+Setup.swift中添加setupQuotes()方法:
@_exported import Vapor
extension Droplet {
public func setup() throws {
setupQuotes()
}
}
現(xiàn)在就可以在我們的controller里面寫增刪改查了:
import Vapor
import FluentProvider
struct QuotesController {
func addRoutes(to drop: Droplet) {
let quots = drop.grouped("api","quots")
//添加一個(gè)新的quots
quots.post("create", handler: createQuots)
//查詢所有的quotes
quots.get(handler: allQuotes)
// 更新quotes
quots.post("update", handler: updateQuotes)
// 刪除quotes
quots.post("delete", handler: deleteQuotes)
}
/// 添加一個(gè)新的quots
func createQuots(_ req: Request) throws -> ResponseRepresentable {
guard let json = req.json else {
throw Abort.badRequest
}
let quots = try Quotes(json: json)
try quots.save()
return quots
}
/// 查詢所有的quots
func allQuotes(_ req: Request) throws -> ResponseRepresentable {
let quots = try Quotes.all()
return try quots.makeJSON()
}
/// 更新quotes
func updateQuotes(_ req: Request) throws -> ResponseRepresentable {
guard let json = req.json else {
throw Abort.badRequest
}
let id: Int = try json.get("id")
if let quots = try Quotes.find(id) {
try quots.update(json: json)
}
return try Quotes.all().makeJSON()
}
// 刪除quotes
func deleteQuotes(_ req: Request) throws -> ResponseRepresentable {
guard let json = req.json else {
throw Abort.badRequest
}
let id: Int = try json.get("id")
if let quots = try Quotes.find(id) {
try quots.delete()
}
return try Quotes.all().makeJSON()
}
}
還需要在Quotes中加入一個(gè)update方法蜓洪,并把參數(shù)改成var
/// 名人名言
final class Quotes: Model {
/// 作者
var author: String
/// 內(nèi)容
var content: String
/// 描述
var description: String
...
}
extension Quotes {
func update(json: JSON) throws {
self.author = try json.get(Quotes.Keys.author)
self.content = try json.get(Quotes.Keys.content)
self.description = try json.get(Quotes.Keys.description)
try self.save()
}
}
現(xiàn)在我們的增刪改查就已經(jīng)完成了纤勒,下面cmd+r運(yùn)行程序,用Rested測試接口:
由于默認(rèn)的數(shù)據(jù)庫是基于內(nèi)存加載的隆檀,重新運(yùn)行程序則會(huì)清空摇天,如果想要保存數(shù)據(jù)到服務(wù)器粹湃,你需要使用持續(xù)化的數(shù)據(jù)庫,如MySQL闸翅、PostgreSQL以及MongoDB再芋,后面我會(huì)對這幾個(gè)數(shù)據(jù)庫操作一一介紹。
關(guān)于Vapor其他知識(shí)坚冀,可以參考以下文章:
Vapor奇幻之旅(01開始)
Vapor奇幻之旅(02部署)
Vapor奇幻之旅(03上手)
Vapor奇幻之旅(04Routing)
Vapor奇幻之旅(05 Fluent)
Vapor奇幻之旅(06 PostgreSQL)
Vapor奇幻之旅(07 連接服務(wù)端PostgreSQL)
Vapor奇幻之旅(08 連接服務(wù)端MongoDB)
Vapor奇幻之旅(09 連接MySQL)
希望你對我的教程能夠喜歡济赎,你們的贊是我持續(xù)的動(dòng)力,歡迎加入QQ群參與互動(dòng):431296189