« Previous 1 2 3 4 Next »
Moving data to Drupal 8
Moving Up
Destination Plugins
The next section of the migration defines a destination plugin, which tells Drupal where to save incoming data:
destination: plugin: "entity:node"
Each pet will be saved as a new node using the entity:node
plugin. Drupal 8 provides most of the destination plugins you will need. Many contributed modules include destination plugins for their own entity types and configuration. You might need to create a custom destination if you want to migrate data into a custom table. For example, pretend that pets should be imported into a custom table instead of nodes:
destination: plugin: pet_dest
The destination plugin is placed in src/Plugin/migrate/destination/PetDestination.php
and must extend \Drupal\migrate\Plugin\migrate\destination\DestinationBase
. Destinations are defined using the @MigrateDestination
annotation. Similar to source plugins, the annotation id
key is referenced in the configuration:
/** * Pet destination. * * @MigrateDestination( * id = "pet_dest" * ) */ class PetDestination extends DestinationBase {
Destination plugins must also describe available fields by implementing MigrateDestinationInterface::fields()
and MigrateDestinationInterface::getIds()
(Listing 5). The plugin overrides MigrateDestinationInterface::import()
to save data to a custom table.
Listing 5
Describe Available Fields
/** * {@inheritdoc} */ public function fields(MigrationInterface $migration = NULL) { return [ 'pid' => $this->t('Pet id'), 'oid' => $this->t('Owner id'), 'type' => $this->t('Pet type'), 'name' => $this->t('Pet name'), 'photo' => $this->t('Pet photo'), ]; } /** * {@inheritdoc} */ public function getIds() { return [ 'pid' => ['type' => 'integer'] ]; }
Assume $this->save()
is defined and handles inserting a new row into the appropriate table. If something goes wrong, throw a MigrateException
(Listing 6). When an exception is thrown, the source row is marked as failed and processing continues to the next row. You can review and fix failed rows after the migration is executed.
Listing 6
Mark Source Row as Failed
/** * {@inheritdoc} */ public function import(Row $row, array $old_destination_id_values = []) { $pet = $this->save($row); if (!$pet) { throw new MigrateException('Could not save pet'); } 10 }
Migrations can be rolled back after testing in case of errors. Rolling back a migration deletes all imported data. The destination plugin is responsible for cleanly removing imported rows in MigrateDestinationInterface::rollback()
. This method is called once for each imported row (Listing 7).
Listing 7
Remove Imported Rows Cleanly
/** * {@inheritdoc} */ public function rollback(array $destination_identifier) { $pet = $this->load(reset($destination_identifier)); if ($pet) { $pet->delete(); } }
Process Plugins
The process key contains mappings from source fields (on the right) to destination fields (on the left). Each mapping is provided by a process plugin (Listing 8). Several process plugins are included in core [5] (see Table 1 for a list of common plugins). If no plugin is provided (e.g., nid: pid
), then Drupal assumes the default get
plugin, which copies source values without any modification. Be sure to include the source
key if a plugin is specified.
Listing 8
Mappings
process: nid: pid title: plugin: callback callable: trim source: name type: plugin: default_value default_value: pet uid: plugin: migration migration: pet_owners source: oid field_pet_type: plugin: cat_to_dog source: type field_photo: picture
Table 1
Common Process Plugins Included in Core
Process Plugin | Function | Example |
---|---|---|
get
|
Copies a value verbatim. The example is the default plugin if none is specified. | name: source_name
|
callback
|
Passes source value through a callable function | title: plugin: callback callable: trim source: title
|
dedupe_entity
|
Ensure a field is unique. A numeric counter will be appended to the value until it is unique. | machine_name: plugin: dedupe_entity entity_type: node field: type postfix: '_'
|
default_value
|
Provide a default value if the source is null, zero, or an empty string. | type: plugin: default_value default_value: dog
|
migration
|
Resolve an ID field mapping from another migration. | uid: plugin: migration migration: pet_owners source: oid
|
skip_on_empty
|
Skip the row if the source value is empty (empty string, FALSE, or 0). | title: plugin: skip_on_empty method: row source: name
|
static map
|
Define a custom mapping for source to destination values. | type: plugin: static_map source: type map: cat: dog fish: bird
|
Process plugins can have different configuration options. The callback
plugin uses the callable
option to pass values through a function. For example, you can trim whitespace from pet names using the callback
plugin with the PHP trim()
function:
title: plugin: callback callable: trim source: name
Several process plugins may be used for a single field. Simply provide a YAML array with multiple plugins and options. The field value will be passed through each plugin with the result from one passed as the input to the next. This is called a process pipeline. The following pipeline passes the source value through the trim()
callback followed by substr
to return the last 10 characters:
title: - plugin: callback callable: trim source: title - plugin: substr start: -1 length: 10
Note that the source key is omitted for all but the first plugin definition. The source is assumed to be the output of the previous plugin.
The type field (field_pet_type
) uses a custom process plugin (cat_to_dog
):
field_pet_type: plugin: cat_to_dog source: type
Custom process plugins extend \ Drupal\migrate\ProcessPluginBase
, implement MigrateProcessInterface::transform()
, and are defined using the @MigrateProcessPlugin
annotation. The cat_to_dog
plugin changes pet type from "cat" to "dog" and is located in src/Plugin/migrate/process/CatToDog.php
(Listing 9).
Listing 9
Custom Process Plugin
/** * Turn cats into dogs. * * @MigrateProcessPlugin( * id = "cat_to_dog", * ) */ class CatToDog extends ProcessPluginBase { /** * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { return ($value == 'cat') ? 'dog' : $value; } }
Migration Dependencies
A migration might require others to be executed first (see the "Watch Out!" box). For example, the uid
field mapping in Table 1 uses the migration
process plugin to reference the pet_owners
migration. Add the pet_owners
migration as a required dependency to make sure it runs first. You can also specify optional dependencies thus,
Watch Out!
While developing your migrations, you will need to disable and re-enable your module regularly. Add the following dependency to all of your YAML configuration files to make sure the configuration is removed and reinstalled along with your module.
dependencies: enforced: module: - MODULENAME
Without this explicit dependency, the configuration will remain in the database, even when your module is disabled, and you will not be able to re-enable the module.
migration_dependencies: required: - pet_owners
to help order migrations correctly.
« Previous 1 2 3 4 Next »
Buy this article as PDF
(incl. VAT)