Hello extension devs!
We're glad to have you and want to make your life easier; unfortunately, today I must report of the opposite. As predicted, we recently broke backwards compatibility in a significant way. The structure of database migrations has been changed. That means: if you extensions use migrations to add to or modify Flarum's database, then they will not be compatible with the upcoming beta.5 release.
Now, because we don't like bringing bad news without good news, here are some good ones: We also made it significantly easier to make migrations (the new way).
So, enough talking. Here's what migrations looked like up until recently (example from the official tags extension):
namespace Flarum\Tags\Migration;
use Flarum\Database\AbstractMigration;
use Illuminate\Database\Schema\Blueprint;
class CreateUsersTagsTable extends AbstractMigration
{
public function up()
{
$this->schema->create('users_tags', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('tag_id')->unsigned();
$table->dateTime('read_time')->nullable();
$table->boolean('is_hidden')->default(0);
$table->primary(['user_id', 'tag_id']);
});
}
public function down()
{
$this->schema->drop('users_tags');
}
}
Instead of classes (whose names, namespaces and autoloading rules are hard to guess for us in a consistent way), these files will now return an array of closures, keyed "up" and "down", which implement the migration logic.
The above example would therefore look like this, given the new structure:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$schema->create('users_tags', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('tag_id')->unsigned();
$table->dateTime('read_time')->nullable();
$table->boolean('is_hidden')->default(0);
$table->primary(['user_id', 'tag_id']);
});
},
'down' => function (Builder $schema) {
$schema->drop('users_tags');
}
];
The parameters passed to these methods do not need to be Builder
instances. You can typehint any class or interface that is bound into the IoC container and Flarum will automatically pass in the correct instance. Typically, this will be either a schema Builder
or Flarum's SettingsRepositoryInterface
.
And here's the best part:
Writing migrations gets very repetitive after a while; and getting the logic for the "down" migration right is boring and error-prone. Since these are often very predictive, we have created a handy collection of shortcuts that make writing migrations for normal use cases (such as creating tables, adding or renaming columns) short and precise:
use Flarum\Database\Migration;
use Illuminate\Database\Schema\Blueprint;
return Migration::createTable(
'users_tags',
function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('tag_id')->unsigned();
$table->dateTime('read_time')->nullable();
$table->boolean('is_hidden')->default(0);
$table->primary(['user_id', 'tag_id']);
}
);
Thanks for building your ideas on top of Flarum while it's still in such an early stage! We hope, these changes make you happy (besides also keeping you busy).