Quick and Dirty Debugging of Drupal 8 Migrations
If you’re working on a migration in Drupal 8 and you’re finding yourself a little confused by the YAML-based configuration, I strongly recommend using a proper debugger so you can step through the code. You cannot step through the YAML, but you can step through the code that the YAML triggers. This blog post is my attempt to share a few tips/tricks I’ve learned along the way. This isn’t meant to be an exhaustive step-by-step debugging tutorial, so you may have to do some Googling to fill in the blanks.
Disclaimer: Some of the information is PHPStorm-specific, but you should be able to adapt to whichever debugging tools you use.
My interactions with Migrate are entirely through drush, so I had to make sure my terminals (iTerm / PHPStorm terminal) are capable of talking to PHPStorm. I do this (once until I reboot or logout) with export XDEBUG_CONFIG="remote_enable=1 remote_mode=req remote_port=9000 remote_host=127.0.0.1 remote_connect_back=0" .
Before you attempt to step through your migration code, please make sure your debugger is catching breakpoints as expected.
Migrate is finicky. When you make a YAML change you have to re-import it into Drupal. If you create new plugins you have to clear the cache. Often you can get away with using something like drush config-import --partial --source=modules/custom/mymigration/config/install -y to refresh the config in your module. Sometimes, however, it requires a little more work. I usually refresh the entire database to ensure there aren’t any artifacts that could cause confusion. Alternatively you could uninstall your migration module, make sure tables are cleared, and re-install.
Watching Values Change As Plugins Modify Them
When you’re trying to populate entity fields with data you often have to do additional processing on the raw data. There are a number of process plugins for this. Because they’re implemented via YAML config it may be hard to make sense of how the data is transforming as it proceeds through the process pipeline. You can easily see the data before and after each plugin with a simple breakpoint and some step-through debugging.
Set a breakpoint in \Drupal\migrate\MigrateExecutable::processRow on the line that reads $value = $plugin->transform($value, $this, $row, $destination);
If you can add a condition to your breakpoint, it’s nice to be able to set it to only catch a particular field. You can do this with something like $destination == 'field_blog_images' . PHPStorm offers this functionality by right-clicking the breakpoint.
When you’re ready to test, initiate an import (for example: drush mi blog --update ). If you’ve setup your debugger to stop on the line mentioned above you should be able to inspect the variables as they exist before being modified by the current plugin. Among the variables you’ll find:
- $plugin – The plugin being used
- $value – The value being transformed
- $destination – The name of the field in the target Drupal entity
- $row – This is where you’ll spend the most time. This contains, most importantly, $source and $destination values.
The first plugin that will be executed is most likely the Get plugin, which grabs the value from the source. If this is your only process plugin for the field, Step Over the line to see what comes into the $value variable.
If you have more process plugins, Resume the debugger to proceed automatically until it hits $plugin->transform again (for the next plugin). You can continue working through and watching the $value change with each plugin that transforms it.
Inspect a Record After It’s Fully Processed
When you want to see each record before it’s saved you can drop a breakpoint in \Drupal\migrate\MigrateExecutable::import on the line that reads $this->processRow($row); . When the debugger stops here you will see the data before we have any $destination data. If you Step Over this line (and you’re not met with an exception) you will see a populated $destination that is the result of all of the processing on all of the fields.
Thanks, helped me a lot.