Home > Backend Development > PHP Tutorial > Database Versioning with Ladder Migrations

Database Versioning with Ladder Migrations

Jennifer Aniston
Release: 2025-02-21 10:30:09
Original
814 people have browsed it

Database Versioning with Ladder Migrations

Core points

  • Ladder is a tool for creating, running, and managing database migrations that allows tracking of changes in database schemas in the same way as application code. This tool can be integrated into any major framework and can be used for changes and feature management in version control.
  • Migrations are always run in sequence, and Ladder ensures this by numbering migrations in sequence and storing records of the migrations that have been run in the database itself, thus preventing rerunning of previous migrations.
  • Ladder also allows pre-population or "seed" databases to be created, such as default user accounts. This can be done using Ladder's key-value store, storing some data for later reference.
  • The tool provides additional commands to manage and monitor databases, such as the status command for database state, the diff and diff-save commands for dumping and restoring database state, and the version commands for checking the version of Ladder used.

Version control systems are invaluable for tracking changes in code, especially when working in teams. However, most applications contain more than just application code. Managing changes to databases has been more challenging, especially when adding new features that require changing patterns.

Suppose you are working on a module and realize that a database table requires an extra column. You might want to open a database query tool or command line and simply add that column. However, this does not leave a record of changes like version-controlled application code. This can be exacerbated when working in a team – if colleagues extract your code changes without running the same database update, then their application version will most likely crash. This becomes even more problematic when you release product updates, as this can break the app not just for your colleagues, but for your users.

One solution is to use migration to transfer the responsibility for creating and modifying database schemas into your code. This way, changes can be managed together with the rest of the application, and we can use features we are accustomed to in version control (such as being able to compare versions and keep audit trails) to handle database changes. It also allows these changes to be seamlessly integrated into the version, as they can be part of the same branch or tag.

Many major frameworks have their own migration implementations, but for those that don't - if you don't use any - you can use Ladder.

Ladder Introduction

Ladder is a tool for creating, running, and managing database migrations. Migration is just a PHP class, so version control can be checked in with the rest of the application's code.

You can make as many changes to the schema in a single migration, although it is best to limit the migration to a single table or feature.

Migrations are always run in order. So, suppose you write a migration to create the products table and create a new migration a few weeks later to add an extra column to it. Trying to run the former before the latter will produce an error. Ladder solves this problem by numbering migrations in sequence and storing records (and time) of running migrations in the database itself.

Installation

Ladder can be downloaded from Bitbucket or through Composer. However, it takes several steps to get up and running.

The easiest way (although admits to being less elegant) is to download or clone it from the project root and place it in a directory called ladder. The problem with using Composer is that running composer update will overwrite your configuration file.

There are five configuration files, each of which needs to be created manually; the easiest way is to copy the provided example:

cp ladder/config/config.php.example ladder/config/config.php
cp ladder/config/database.php.example ladder/config/database.php
cp ladder/config/diff.php.example ladder/config/diff.php
cp ladder/config/editor.php.example ladder/config/editor.php
cp ladder/config/table.php.example ladder/config/table.php
Copy after login
Copy after login

You may just need to modify database.php (which contains database connection details) and editor.php, where you can specify the preferred text editor, and choose to automatically open a new migration when created.

Create migration

Let's start by creating a migration to create the users table.

On the command line:

php ladder/ladder.php create create_users_table
Copy after login
Copy after login

This creates a file named ladder/migrations/00001_create_users_table, which by default contains a basic structure with commented out example calls. If you have set auto-edit to true in ladder/config/editor.php, this file will be opened immediately in the specified text editor. You can call migrations at will, but it will be helpful to be able to see what the migration does from the file name at a glance.

Here is what the file might look like (I deleted the commented out line of code for clarity):

class Create_Users_Table_Migration_00001 extends Migration {
    protected $min_version = '0.8.1';

    public function up() {
        $this->create_table('users')
            ->column('email', 'varchar', array('limit' => 128, 'null' => FALSE))
            ->column('password', 'varchar', array('limit' => 32, 'null' => FALSE));
    }

    public function down() {
        $this->table('users')->drop();
    }   
}
Copy after login
Copy after login

Call the up() method when the migration is run, and the down() method when the migration is rolled back - so it always needs to perform the opposite operation to the up() method. In this example, the up() method creates a table named users, and the down() method deletes it.

The

create_table() method returns a reference to the new table, while the Table class has a column() method to add a new column. It has a smooth interface so you can link them together to create multiple columns at the same time. You will notice that there is no ID column - this is automatically created - i.e. an auto-incremental integer primary key named id.

table() returns a reference to the table, but it also creates the table if the table does not exist yet - so you can safely change the create_table() call to table()

Let's create another migration, this time creating roles table:

php ladder/ladder.php create create_roles_table
Copy after login
Copy after login

File itself:

class Create_Roles_Table_Migration_00002 extends Migration {
    protected $min_version = '0.8.1';

    public function up() {
        $this->table('roles')
            ->column('nme', 'varchar', array('limit' => 128, 'null' => FALSE));            
    }

    public function down() {
        $this->table('roles')->drop();
    }   
}
Copy after login
Copy after login

Now you need to actually run the migration. To do this:

php ladder/ladder.php migrate
Copy after login
Copy after login
Copy after login
Copy after login

If you look at the database, you will find four tables:

migrations are created automatically to track which migrations have been run migrations_kvdata is also created for you, and your migrations can be used for any key-value storage users and roles are the tables we just added.

However, if you pay close attention to roles migration, you will notice that it creates a column called nme instead of name. At this point, we can fix this by "undoing" the migration, modifying the class, and running it again. To roll back the migration:

cp ladder/config/config.php.example ladder/config/config.php
cp ladder/config/database.php.example ladder/config/database.php
cp ladder/config/diff.php.example ladder/config/diff.php
cp ladder/config/editor.php.example ladder/config/editor.php
cp ladder/config/table.php.example ladder/config/table.php
Copy after login
Copy after login

Number 2 indicates the migration to be rolled back to - it is the prefix of the migration file name, without leading zeros.

Now you can simply make the correction and run the migration again:

php ladder/ladder.php create create_users_table
Copy after login
Copy after login

Because the migrations table has stored records of running and unrun content, you don't need to worry that your first migration will be rerun.

There is also a faster way to use reapply:

class Create_Users_Table_Migration_00001 extends Migration {
    protected $min_version = '0.8.1';

    public function up() {
        $this->create_table('users')
            ->column('email', 'varchar', array('limit' => 128, 'null' => FALSE))
            ->column('password', 'varchar', array('limit' => 32, 'null' => FALSE));
    }

    public function down() {
        $this->table('users')->drop();
    }   
}
Copy after login
Copy after login

This will call the second migration's down() method at once, and then its up() method.

Now let's say after a while, we develop a new feature that requires the users table to contain a status field. To do this, we need to create a new migration:

php ladder/ladder.php create create_roles_table
Copy after login
Copy after login

The migration will look like this:

class Create_Roles_Table_Migration_00002 extends Migration {
    protected $min_version = '0.8.1';

    public function up() {
        $this->table('roles')
            ->column('nme', 'varchar', array('limit' => 128, 'null' => FALSE));            
    }

    public function down() {
        $this->table('roles')->drop();
    }   
}
Copy after login
Copy after login

As before, run with the following command:

php ladder/ladder.php migrate
Copy after login
Copy after login
Copy after login
Copy after login

Now, if you check your database, you will see that the users table has a new column.

Database seeding

In addition to writing migrations to manage database schemas, you can also use Ladder to pre-populate (i.e. seed) databases.

For example, you can extend the create_users_table migration to create a default root user account:

php ladder/ladder.php remove 2
Copy after login

Note that we are using the set() and get() methods to take advantage of Ladder's key-value store, storing the user ID so that we can refer to it later.

You can also import data from migrated CSV files, for example:

php ladder/ladder.php migrate
Copy after login
Copy after login
Copy after login
Copy after login

To update instead of inserting CSV data, you can do this:

php ladder/ladder.php reapply 2
Copy after login

In this case, the send parameter means we want to run UPDATE, and the third parameter contains a list of key fields to determine which records to update.

Add other databases

You will notice that the default database configuration file ladder/config/database.php demonstrates how to add additional database connections; perhaps for staging or real-time databases. For example:

php ladder/ladder.php create add_status_to_users_table
Copy after login

You can specify the connection to use like this:

class Add_Status_To_Users_Table_Migration_00003 extends Migration {
    protected $min_version = '0.8.1';

    public function up() {
        $this->table('users')
            ->column('status', 'integer', array('null' => FALSE, 'default' => 0));            
    }

    public function down() {
        $this->table('users')->drop_column('status');      
    }
}
Copy after login

Other commands

Status

You can use the status command to get the database status:

php ladder/ladder.php migrate
Copy after login
Copy after login
Copy after login
Copy after login

Example output: (The example output is omitted here because the original document does not provide specific output content)

diff and diff-save

(The descriptions of the diff and diff-save commands are omitted here, as these commands have been described in detail in the original document)

version

(The description of the version command is omitted here, because the command has been described in detail in the original document)

Summary

This article introduces Ladder, used to maintain database schema and pre-populate data. (The summary part is omitted here, because the original document has summarized Ladder)

FAQs about database versioning and Ladder migration

(The FAQ section is omitted here, as the original document already provides detailed FAQ)

The above is the detailed content of Database Versioning with Ladder Migrations. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template