Hey,

after debugging for now around 5 hours I give up and have to ask.
How is it possible to start a drupal 8 migration programmatically? This seems like something that should be very simple, but I can not figure out how to do it?

Greetings Sebastian

Comments

sgurlt created an issue. See original summary.

cilefen’s picture

Priority: Major » Normal

Support requests are Normal priority.

mikeryan’s picture

Status: Active » Fixed

The basic principle is to create an instance of your migration via the plugin manager, construct a MigrateExecutable object from that migration, and call $executable->import(). E.g.

$migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id);
$executable = new MigrateExecutable($migration, new MigrateMessage());
$executable->import().

Full real-world examples can be found in core and contrib.

sgurlt’s picture

This is perfect, thanks a lot :)

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

andres.torres’s picture

Hi all,

I'm having a hard time trying to have the code above to work on a hook_cron on D8, but I'm always getting the following error when running cron:

TypeError: Argument 1 passed to Drupal\migrate_tools\Controller\MigrationController::__construct() must be an instance of Drupal\migrate_plus\Plugin\MigrationConfigEntityPluginManager, none given, .......

Ideally i'd like to run a migration and add additional operations through this hook.
Here's my sample code, hope anyone can take a look and point me in the right direction.
Thanks in advance!

<?php
/**
* @file
*/

use Drupal\migrate\Row;
use Drupal\migrate\MigrateExecutable;
use Drupal\migrate\MigrateMessageInterface;
use Drupal\migrate\MigrateMessage;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Event\MigrateEvents;

use Drupal\migrate_plus\Entity\Migration;
use Drupal\migrate_plus\Entity\MigrationGroup;
use Drupal\migrate_plus\Plugin\MigrationConfigEntityPluginManager;

use Drupal\migrate_tools\Controller\MigrationController;

/**
* Implementation of hook_cron().
*/
function my_module_cron() {

// Get migration object
$migration_id = 'my_migration_name';
/** @var \Drupal\migrate\Plugin\Migration $migration */
$migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id);
$executable = new MigrateExecutable($migration, new MigrateMessage());
$ex = $executable->import();
//drupal_set_message('');
}

sjpeters79’s picture

Andres, you may want to try the following:

$migration = Drupal::service('plugin.manager.config_entity_migration')->createInstance($migration_id);
saranya ashokkumar’s picture

Hi,
I have created a form with file field.
On submit I have to run migration programmatically.
By passing migration_id, I have created the instance. but the problem is that, I need to change the source.urls dynamically by getting the file path from form.
I have set the source url by config set before importing migration, but on create instance the url is not getting change.
Can anyone suggest me, how to change the migration url dynamically before import.

Thanks,
Saranya.P

sleopold’s picture

saranya, you can override the source config when you create the plugin instance:

if ($path = $form_state->getValue('import_csv')) {
  $migration = $this->migrateManager->createInstance($form_state->getValue('migrate_plugin'), [
    'source' => [
      'path' => $path,
    ],
  ]);
  
  $executable = new MigrateExecutable($migration, new MigrateMessage());
  $executable->import();
}
punamshelke’s picture

Hi,

I have imported migration in the same way and its working for me.
now i have to print the report like total counts etc.
like response printing after drush command..

is their any way to print?

sgurlt’s picture

Hey,

I would try it like this:

https://stackoverflow.com/a/6674348/1565249

Cheers

punamshelke’s picture

Hi,

Can we add limit to execute the migration as i have to import content in batch of 100...
I am executing migration through programmatically...

Thanks

drikc’s picture

Found that, by using the migrate_tools module you can re-write the example in #3 as follow which allows to pass some options:

$migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id);
$executable = new \Drupal\migrate_tools\MigrateExecutable(
  $migration,
  new \Drupal\migrate\MigrateMessage(),
  [
    'limit' => 10,
  ]
);
$executable->import();
aperedos’s picture

There are any way to execute an update of a migrate programmatically?

jackbravo’s picture

The way shown here helped me a lot. And combined with the embbeded_data plugin I found that you can execute a migration with a data array if you already have the data in PHP.


$data = [
  ['key' => '1', 'field1' => 'f1value1', 'field2' => 'f2value1'],
  ['key' => '2', 'field1' => 'f1value2', 'field2' => 'f2value2'],
];
$migration = \Drupal::service('plugin.manager.migration')->createInstance($migrate_id, [
  'source' => [
    'plugin' => 'embedded_data',
    'data_rows' => $data,
   ],
]);
$executable = new MigrateExecutable($migration, new MigrateMessage());
$executable->import();

jackbravo’s picture

Just don't use this approach to do a migration inception (launching a migration from inside another migration) because at least on the ProcessPlugin where I tried doing that it ended up breaking the --limit parameter when launching a migration from drush that was using another migration inside of it.

jnrmprd’s picture

I wanted to launch a migration with an update option, so I've use that (taken from the Drush Command migrate_tools.drush.inc):

<?php
$migration = \Drupal::service('plugin.manager.migration')->createInstance($migration_id);
$migration->getIdMap()->prepareUpdate(); // <-- this :)
$executable = new \Drupal\migrate_tools\MigrateExecutable($migration, new \Drupal\migrate\MigrateMessage());
$executable->import();
?>
seth.e.shaw’s picture

@jackbravo, where did you find the embedded_data plugin you mentioned in #15? That would be really useful right now.

Edit: never mind; I found it. It is a core plugin.

tiagopastor’s picture

#17 works for me, thanks

annie2512’s picture

#15 worked well for me.
I wanted to change the source plugin urls dynamically( the changed part of the urls is the API version which is imported in a previous migration, and stored in a config field).
I implemented it using an event subscriber on migration pre-import event, but somehow the first time I ran the import the API version values were not being changed. This method works all the time. Thanks @jackbravo

buenos’s picture

Is it possible to execute a group migration in a similar way?
With Drush we would do smth like "drush migrate:import --group=my_group".
How would one execute that from code when there is no migration id to be passed?