skip to Main Content

How to remove a category group via migration in Craft CMS v3

  • By , Director of Engineering, Culture Foundry

We are using Craft CMS for a client website that is too complicated for WordPress and not complex enough for Drupal. One of the great things about Craft is that they’ve thought about how to move configuration from development to production. This is required for almost any site of any size, since developers should be making changes in the development environment but need a way to migrate the code and content structure changes to staging and then production. I’m not sure they’ve entirely solved this issue, but they’ve taken a crack at it.

With Craft v3, the preferred tool to manage moving data and configuration changes is migrations. If you use the migration manager plugin you can easily generate migrations from manual actions. If you add a field or a categorygroup using the control panel locally, you can export the configuration to a migration, which is stored on the filesystem and can be versioned. Then you can run that migration in staging and be guaranteed that the same categorygroup will be created there (and thence on to production). This is awesome, because there are other CMSes out there that require manual configuration of aspects of their system. If that is the case, you need to capture that configuration in a document and make sure that someone executes every step of it in deployment. Humans are prone to fail to record needed actions or to skip steps, leading to environments that are subtly out of sync.

The migration manager tool lets you easily add any new content structure, but I couldn’t find a way to make it remove an extraneous one. For example, we had a categorygroup that had been added early and, through our development, we’d learned it was unneeded. We could disable it and capture that via the migration manager, but you can’t delete the categorygroup via the migration manager (here’s a list of operations they support). For deletion, you need to write code. The rest of this post will walk through that process.

  • Login to the server where your development environment is.
  • Login to the development control panel.
  • Make sure you have migration manager installed. Export your categorygroup as a migration, called something like ‘removeBlogCategorygroup’. This will export JSON configuration to recreate your categorygroup, but it will put it in the ‘safeUp’ method. The migration manager will place a file in the `migrations` subfolder of your site.
  • Edit the generated migration file in the terminal and move it to the ‘safeDown’ method, replacing the default code block.
  • Add this code to the ‘safeUp’ method (this example is is for categorygroups, but there is an analogous service with a delete method for other content structures. See the other public properties of the $app object for more services):
$categoryGroupName = 'Blog';
$group = \Craft::$app->categories->getGroupByHandle($categoryGroupName);
return \Craft::$app->categories->deleteGroupById($group->id)
  • Run the migration up and down and then up again to make sure that you’ve set up the migration to go both ways. If this fails, you’ll need to troubleshoot. The first few times you do this, you may want to make a backup of your local database so that if you really mess things up you can just re-import and try again.
./craft migrate/up --interactive 0 && ./craft migrate/down --interactive 0 && ./craft migrate/up --interactive 0
  • Commit the migration to version control.
  • Login to your staging server, pull the code, and run the up migration. If you are using a tool like circleci, you can also set up a ssh command to run migrations automatically. Something like this:
 ssh <host> php craft migrate/up --interactive 0
  • Rinse and repeat for the user acceptance testing environment and/or production.

Happy migrating!

Back To Top