DRUPAL MIGRATE: SET AUTOMATIC ID ON CSV IMPORTS

The "Migrate" module in the core is one of my favourite parts of Drupal 8 and 9. It's super flexible and makes migrating content from any source you can imagine pretty easy. Today I want to show a trick I use when I receive a csv (or excel file) from clients, where they want all the content migrated to Drupal. A very simple example would be a list of categories.

Usually, the file will come with a term on each line. However, the migrate module would want us to set an ID for all terms, which currently none of the rows has. One solution to this is to place an ID on all the rows manually with some kind of spreadsheet software and then set up our migration to the new column to detect the IDs. But since both involve the words "manual" and "spreadsheet software", it immediately makes me want to come up with another solution. Is there any way we can set the row id programmatically based on the row number? Of course, there is!

So, here's a trick I use to set the row number id:

The migration configuration looks like this:

id: my_module_categories_csv
label: My module categories
migration_group: my_module
source:
  # We will use a custom source plugin, so we can set the 
  # ID from there.
  plugin: my_module_categories_csv
  track_changes: TRUE
  header_row_count: 1
  keys:
    - id
  delimiter: ';'
  # ... And the rest of the file 

As indicated in the yaml file, we will use a custom source plugin for this. Let's say we have a custom module called "my_module". Inside that module folder, we create a file called Categories Csv.php inside the src/Plugin/migrate/source/CategoriesCsv.php folder. And in that file we put something like this:

<?php
namespace Drupal\my_module\Plugin\Migrate\source;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Drupal\migrate_source_csv\Plugin\migrate\source\CSV;
/**
 * Source plugin for Categories in csv.
 *
 * @MigrateSource(
 *   id = "my_module_categories_csv"
 * )
 */
class CategoriesCsv extends CSV {
  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    // Delta is here the row number.
    $delta = $this->file->key();
    $row->setSourceProperty('id', $delta);
    return parent::prepareRow($row);
  }
}

In the above code, we set the source property of id to delta (the row number). This means you can have a source like this:

Name
Category1
Category2
Category3

Instead of this

id;Name
1;Category1
2;Category2
3;Category3

The best part of this is that when your client changes their mind, you can update the file instead of editing it before updating it. And by editing, I mean "manually" and with "spreadsheet software". 

Have Any Project in Mind?

If you want to do something in Drupal maybe you can hire me.

Either for consulting, development or maintenance of Drupal websites.