> adonis make:migration users
You are viewing the legacy version of AdonisJS. Visit https://adonisjs.com for newer docs. This version will receive security patches until the end of 2021.
Migrations are documented database mutations, created throughout your application’s development lifecycle that you can roll back or re-run at any point in time.
Migrations make it easier to work as a team, enabling database schema changes from one developer to be easily tracked and then applied by other developers in your organization.
To use migrations, the Migrations Provider must first be registered inside the start/app.js file’s aceProviders array.
|
Let’s create a users table with the help of migrations.
First, call the adonis make:migration
command to create a schema file:
> adonis make:migration users
When prompted, choose the Create table
option and press Enter:
✔ create database/migrations/1502691651527_users_schema.js
Your new schema file (prefixed with the current timestamp) is created in the database/migrations
directory, ready to modify as required:
'use strict'
const Schema = use('Schema')
class UsersSchema extends Schema {
up () {
this.create('users', (table) => {
table.increments()
table.timestamps()
})
}
down () {
this.drop('users')
}
}
module.exports = UsersSchema
A schema file requires two methods: up
and down
.
The up
method is used to take action on a table. It can be used to create a new table or altering an existing table.
The down
method is used to revert the changes applied in the up
method. When up
is used to create a table, down
would be used to drop that table.
Update the schema file you just created with the following code:
'use strict'
const Schema = use('Schema')
class UsersSchema extends Schema {
up () {
this.create('users', (table) => {
table.increments()
table.string('username', 80).notNullable().unique()
table.string('email', 254).notNullable().unique()
table.string('password', 60).notNullable()
table.timestamps()
})
}
down () {
this.drop('users')
}
}
module.exports = UsersSchema
The example above demonstrates how to create/alter a database table using schema files, chaining together different column type/modifier methods to define the characteristics of individual field attributes in the up
method.
For the full list of schema column type and modifier methods, see the Knex API documentation. |
Method | Description |
---|---|
|
Adds a bigint column. |
|
Adds a binary column. |
|
Adds a boolean column. |
|
Adds a date column. |
|
Adds a datetime column. |
|
Adds a decimal column. |
|
Adds a enum column. |
|
Adds a float column. |
|
Adds an auto incrementing column. |
|
Adds an integer column. |
|
Adds a json column. |
|
Adds a string column. |
|
Adds a text column. |
|
Adds a time column. |
|
Adds a timestamp column. |
|
Adds created/updated columns. |
|
Adds a uuid column. |
Method | Description |
---|---|
|
Set column to be inserted after |
|
Marks the column as an alter/modify. |
|
Set column collation (e.g. |
|
Set column comment. |
|
Set column default value. |
|
Set column to be inserted at the first position. |
|
Specifies column as an index. |
|
Set foreign key table (chain after |
|
Set column to not null. |
|
Set column to be nullable. |
|
Set column as the primary key for a table. |
|
Set foreign key column. |
|
Set column as unique. |
|
Set column to unsigned (if integer). |
Schema files can use a different connection by defining a connection
getter (ensure your different connection exists inside the config/database.js
file):
const Schema = use('Schema')
class UsersSchema extends Schema {
static get connection () {
return 'mysql'
}
// ...
}
module.exports = UsersSchema
The database table adonis_schema is always created inside the default connection database to manage the lifecycle of migrations (there is no option to override it).
|
We need to call the migration:run
command to run migrations (which executes the up
method on all pending migration files):
> adonis migration:run
migrate: 1502691651527_users_schema.js
Database migrated successfully in 117 ms
You can check the status of all migrations by running the following command:
> adonis migration:status
The batch value exists as a reference you can use to limit rollbacks at a later time. |
That is how migrations work under the hood:
Calling adonis migration:run
runs all pending schema files and assigns them to a new batch.
Once a batch of migration files are run, they are not run again.
Calling adonis migration:rollback
rollbacks the last batch of migrations in reverse order.
Don’t create multiple tables in a single schema file. Instead, create a new file for each database change. This way you keep your database atomic and can roll back to any version. |
Below is the list of available migration commands.
Command | Description |
---|---|
|
Create a new migration file. |
|
Run all pending migrations. |
|
Rollback last set of migrations. |
|
Rollback all migrations to the |
|
Rollback all migrations to the |
|
Get the status of all the migrations. |
For detailed command options, append --help
to a each migration command:
> adonis migration:run --help
Usage:
migration:run [options]
Options:
-f, --force Forcefully run migrations in production
-s, --silent Silent the migrations output
--seed Seed the database after migration finished
--log Log SQL queries instead of executing them
About:
Run all pending migrations
Below is the list of schema methods available to interact with database tables.
Create a new database table (only if it doesn’t exist):
up () {
this.createIfNotExists('users', (table) => {
})
}
Select a database table for alteration:
up () {
this.alter('users', (table) => {
// add new columns or remove existing
})
}
Run an arbitrary SQL query:
up () {
this
.raw("SET sql_mode='TRADITIONAL'")
.table('users', (table) => {
table.dropColumn('name')
table.string('first_name')
table.string('last_name')
})
}
Returns whether a table exists or not (this is an async
method):
async up () {
const exists = await this.hasTable('users')
if (!exists) {
this.create('up', (table) => {
})
}
}
Below is the list of extension methods you can execute when running migrations.
Extensions only work with a PostgreSQL database. |
Create a database extension:
class UserSchema {
up () {
this.createExtension('postgis')
}
}
Create a database extension (only if doesn’t exist):
class UserSchema {
up () {
this.createExtensionIfNotExists('postgis')
}
}
Drop a database extension:
class UserSchema {
down () {
this.dropExtension('postgis')
}
}
Drop a database extension (only if it exists):
class UserSchema {
down () {
this.dropExtensionIfExists('postgis')
}
}
Commands written inside the up
and down
methods are scheduled to be executed later inside a migration.
If you need to execute arbitrary database commands, wrap them inside the schedule
function:
class UserSchema {
up () {
// create new table
this.create('new_users', (table) => {
})
// copy data
this.schedule(async (trx) => {
const users = await Database.table('users').transacting(trx)
await Database.table('new_users').transacting(trx).insert(users)
})
// drop old table
this.drop('users')
}
}
The schedule method receives a transaction object. It is important to run all database commands inside the same transaction, otherwise your queries will hang forever.
|
The schema builder API uses the Knex API, so make sure to read their documentation for more information.
Knex has a method called knex.fn.now(), which is used to set the current timestamp on the database field.
In AdonisJs, you reference this method as this.fn.now()
:
up () {
this.table('users', (table) => {
table.timestamp('created_at').defaultTo(this.fn.now())
})
}