0

I have a D8 migration where I pull remote resources and for each one I create new entity object, apply the resource onto the entity via custom methods on that entity and return the data for this resource as $entity->toArray(). This is how my iterator is getting build. So basically it is an array of entity definitions.

On the target entity I have a field called 'name' which is a unique fields so no two entities with the same 'name' can exist. In the migration I have this field as id key. But for some reason when I run the migration it tries to create a new entity and so the UniqueField constraint will prevent the entity to be saved(I am doing validation in entity's preSave() method) and my migration will fail.

And I cannot figure out why it won't match the existing entity if the 'name' field has a value(I have checked this on multiple places in the code).

The only thing I can come up with it so try to load an existing entity in the prepareRow() myself but that seems as very strange approach and I could basically just completely scratch the migration and write a simple batch.


This is my iterator:

  /**
   * {@inheritdoc}
   */
  protected function initializeIterator() {
    $items = $this->getResourceEntity()->getResourcePlugin()->loadAll();
    $storage = $this->entityManager->getStorage($this->getDerivativeId());

    $items = array_map(function($resource) use ($storage) {
      $entity = $storage->create();
      $entity->resourceMap($resource);
      return $entity->toArray();
    }, $items);

    return new \ArrayIterator($items);
  }

After debugging \Drupal\migrate\Plugin\migrate\id_map\Sql::sourceIdFields and \Drupal\migrate\Plugin\migrate\id_map\Sql::destinationIdFields it looks like it tries to map 'name' => 'id' fields for some reason instead of 'name' => 'name'.

I guess that is because the destination plugin(content entity) returns the entity id field which in this case is id in \Drupal\migrate\Plugin\migrate\destination\EntityContentBase::getIds.

I guess I am missing some crucial information here on how the migrations work.

So yeah, I had to use 'id' in getIds(), and in the iterator I had to try to figure out entity id of an existing entity.

1 Answer 1

2

It's rather premature to create an entity at the source plugin, when the destination plugin will create the entity for you... It's much simpler for the iterator to simply produce an array of fields representing the raw data, have the process pipeline map those source fields to the Drupal destination entity's field names, and have the destination plugin 'entity:my_entity' create and save the entity to Drupal.

2
  • That's what I'm doing. I am only creating stubs, I'm not saving them.
    – user21641
    Commented Nov 29, 2016 at 15:28
  • But why are you creating entities in the source plugin? Normally your source plugin would simply create an array of the source data to iterate over.
    – Mike Ryan
    Commented Dec 4, 2016 at 16:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.