Skip to content

Getting Started with Fluent

Fluent provides an easy, simple, and safe API for working with your persisted data. Each database table/collection is represented by a Model that can be used to interact with the data. Fluent supports common operations like creating, reading, updating, and deleting models. It also supports more advanced operations like joining, relating, and soft deleting.

Note

Don't forget to add import FluentProvider (or your other database provider) to the top of your Swift files.

Fluent ships with SQLite by default. You can use SQLite to quickly scaffold your application with the in-memory database it provides. This is enabled by default in Vapor's default template. To learn more about configuring your database, check out the available drivers.

Creating a Model

Models are the Swift representations of the data in your database. As such, they are central to most of Fluent's APIs.

Let's take a look at what a simple model looks like.

final class Pet: Model {
    var name: String
    var age: Int
    let storage = Storage()

    init(row: Row) throws {
        name = try row.get("name")
        age = try row.get("age")
    }

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    func makeRow() throws -> Row {
        var row = Row()
        try row.set("name", name)
        try row.set("age", age)
        return row
    }
}

Here we are creating a simple class Pet with a name and an age. We will add a simple init method for creating new pets.

Storage

The storage property is there to allow Fluent to store extra information on your model--things like the model's database id.

Row

The Row struct represents a database row. Your models should be able to parse from and serialize to database rows.

Parse

Here's the code for parsing the Pet from the database.

final class Pet: Model {
    ...

    init(row: Row) throws {
        name = try row.get("name")
        age = try row.get("age")
    }
}

Serialize

Here's the code for serializing the Pet to the database.

final class Pet: Model {
    ...

    func makeRow() throws -> Row {
        var row = Row()
        try row.set("name", name)
        try row.set("age", age)
        return row
    }
}

Preparing the Database

In order to use your model, you may need to prepare your database with an appropriate schema.

Preparation

You can do this by conforming your model to Preparation.

extension Pet: Preparation {
    static func prepare(_ database: Database) throws {
        try database.create(self) { pets in
            pets.id()
            pets.string("name")
            pets.int("age")
        }
    } 

    static func revert(_ database: Database) throws {
        try database.delete(self)
    }
}

Here we are creating a simple table that will look like this:

id name age
<database id type> string int

Add to Droplet

Now you can add your model to the config's preparations so the database is prepared when your application boots.

import Vapor
import FluentProvider

let config = try Config()
config.preparations.append(Pet.self)
let drop = try Droplet(config)

...

Using Models

Now that we have created our model and prepared the database, we can use it to save and fetch data from the database.

Save

To save a model, call .save(). A new identifier for the model will automatically be created.

let dog = Pet(name: "Spud", age: 5)
try dog.save()
print(dog.id) // the newly saved pet's id

Find

You can fetch a model from the database using it's ID.

guard let dog = try Pet.find(42) else {
    throw Abort.notFound
}

print(dog.name) // the name of the dog with id 42

Filter

You can also search for models using filters.

let dogs = try Pet.makeQuery().filter("age", .greaterThan, 2).all()
print(dogs) // all dogs older than 2

Drivers

Check out the database section for more information about different database drivers you can use with Fluent.