We build a simple content migration that creates a new channel section in our Craft project.
Let’s start out by creating a simple migration file for creating a new section. Our ultimate goal is to house the entire contact form creation process in one migration file — for the sake of portability — but let’s start simple!
The first step is to create the migration file. Using Craft and Yii, we can easily create new migration file using the migrate/create
command.
The command has one required argument, which is the name of the migration. Craft will prepend a timestamp to it, so the migration file has a unique name.
craft migrate/create add_contact_form_section
The resulting file will be stored in the migrations
directory of your project and named something like m21105_144903_add_contact_form_section
Let’s edit that file and build our first migration!
The two parsts of a migration file that do the work are the safeUp
and safeDown
methods. These are the transcational migration versions of up
and down
.
These methods are considered safe because the entire migration will succeed or fail as a whole. This maintains the integrity of the database in the event that there’s an issue with the migration partway through. Since the entire migration either fails or suceeds, you won’t ever get into the situation of having your database in an unstable state.
safeUp
allows you to make changes to the database via the code inside of the method. For content migrations, this is where you add a new field, section, user, or entry. Anything, really, that isn’t tied to installing or updating a plugin (plugins have their own migrations).
safeDown
allow you to rollback the changes made in safeUp
.
To test out our new migration file, let’s create a new section in our Craft installation.
We could create that section via the Craft control panel UI but the idea here is that we want to script everything so the next time we need to add a contact form to a project, we can just drop the migration files into our project and then run them. Since the migration is self-contained, it doesn’t require anything else except for a properly running installation of Craft.
The first thing we want to do is define our new section. We can do that via the Section model that Craft provides.
We’ll first import it into our migration file:
use craft\models\Section;
And then we can use the model to define our new section inside of the safeUp
method.
The section constructor takes an array of settings as name, value pairs in order to initialize the object.
$section = new Section([
]);
We’ll give our section a name, handle, type (channel), and then the section settings for the site.
$section = new Section([
'name' => 'Contact Form',
'handle' => 'contactForm',
'type' => Section::TYPE_CHANNEL,
'siteSettings' => []
]);
The site settings take an array of data and we need to populate that using a siteSettings
model. Let’s first import that class into our migration file:
use craft\models\Section;
use craft\models\Section_SiteSettings;
And then we’ll define three items in the settings: siteId
, enabledByDefault
, and hasUrls
.
We’d like his section to be part of the primary site (and we only have one site in this installation), we want it enabled by default, and we don’t want it to have URLs.
Because we’re saving contact form submissions as entries in a section, we don’t want that data available at any URLs at all.
$section = new Section([
'name' => 'Contact Form',
'handle' => 'contactForm',
'type' => Section::TYPE_CHANNEL,
'siteSettings' => [
new Section_SiteSettings([
'siteId' => Craft::$app->sites->getPrimarySite()->id,
'enabledByDefault' => true,
'hasUrls' => false
])
]
]);
Now that we have our new section defined, we can create and save it using the saveSections
method in the sections service. The method takes one required parameter, which is the new section we want to save.
$section = new Section([
'name' => 'Contact Form',
'handle' => 'contactForm',
'type' => Section::TYPE_CHANNEL,
'siteSettings' => [
new Section_SiteSettings([
'siteId' => Craft::$app->sites->getPrimarySite()->id,
'enabledByDefault' => true,
'hasUrls' => false
])
]
]);
Craft::$app->sections->saveSection($section)
Let’s make it easy to undo our migration by defining some instructions for the safeDown
method. What we want to do is get the section by handle and then pass it into the deleteSectionById
method and remove the section.
public function safeDown()
{
$section = Craft::$app->sections->getSectionByHandle('contactForm');
return (Craft::$app->sections->deleteSectionById($section->id));
}
I know the section handle will be contactForm
because that’s what I defined it as in the safeUp
code. Once I fetch that section by handle, then I can just get the ID and pass that into deleteSectionById()
.
Now we are ready to test our new migration!
First, we’ll create the new section by running the migration’s safeUp
method. There are two ways to do that:
Running the migration from the Craft control panel requires navigating to the Utilities section and then choose Migrations. The migration should show up with a status of new. If we click “Apply New Migrations”, then the migration will run. There is not, however, a way to rollback a migration from within the control panel. If you want to do that, you’d need to use the command line (which sounds like a good safety feature!).
But let’s run our migration from the command line, so we can get used to the command.
First, let’s make sure our migration is ready to run.
craft migrate/new
And the output should look something like this:
Found 1 new migration:
m211015_144903_add_contact_form
That looks good. Let’s run the new migration and create our new section. This command will run all new migrations and appy their changes to the database.
craft migrate/up
Total 1 new migration to be applied:
m211015_144903_add_contact_form
Apply the above migration? (yes|no) [no]:yes
*** applying m211015_144903_add_contact_form
*** applied m211015_144903_add_contact_form (time: 0.060s)
When we look at our sections list in the control panel, we should see the new Contact Form section.
Congrats, you built your first content migration!
Content Migrations in Craft is made up of the following videos: