首页 > 解决方案 > D8 迁移到附加到帐户的 field_ip 地址

问题描述

我正在处理 D8 中的迁移脚本,该脚本从 MySQL 数据库中提取,并将填充由该模块创建的 D8 中的表......

https://github.com/bjaxelsen/field_ipaddress 这个模块是这个的D8端口... https://www.drupal.org/project/field_ipaddress

无论如何,我安装了模块并将该字段添加到具有无限数量值的帐户中。

一般用户迁移已经完成并且工作正常。它将用户名、电子邮件和状态迁移到 Drupal,一切都很好。

第二个迁移是将用户 IP 地址列表移动到 D8 中。我的数据集将如下所示...

user_id  slstatus   status_id   ipFrom   ipTo       modifyDateUnix
50374    1          0           1.1.1.1  1.1.1.1    1505415351
25108    0          1           4.4.4.0  4.4.4.255  1479243329

真正的代码在mysql中运行INET_ATON函数返回整数,不过上面是为了说明意图。

在准备行函数中,我还获取 IP 地址并将它们转换为 db 表存储所需的十六进制值。

slstatus 与用户的活动状态有关,status_id 与 ip 记录的状态有关。这些用于确定称为已删除的新变量。我还创建了一个名为 idx 的变量,它是一个......以及一个索引。所有这些新字段都添加回该行。

我的 YAML 看起来像这样,是我头疼的地方......

id: UserIpsMigrate
migration_group: 'UMG'
label: 'User IP Migration'
source:
  plugin: UserIpsMigrate
process:
  'field_ip_address/bundle': 'user'
  'field_ip_address/deleted': deleted
  'field_ip_address/entity_id':
    plugin: migration_lookup
    migration: UserMigrate
    source: user_id
  'field_ip_address/revision_id':
    plugin: migration_lookup
    migration: UserMigrate
    source: user_id
  'field_ip_address/langcode': 'en'
  'field_ip_address/delta': idx
  'field_ip_address/field_ip_address_ip_ipv6': 0
  'field_ip_address/field_ip_address_ip_from': ipFrom
  'field_ip_address/field_ip_address_ip_to': ipTo
destination:
  plugin: entity:user
  default_bundle: migration
  migration_dependencies:
    required:
      - user_migrate

我得到的错误表明这个迁移正在尝试创建一个用户......这将导致这些数据失败,所以我确定我需要使用不同的目标插件,但我不知道...... 1)哪个目的地我应该使用的插件 2)如果我的 yaml “脱轨”

标签: migrationdrupal-8

解决方案


我找到了解决方案。

首先,我将 yaml 文件更改为如下所示。

id: UserIpsMigrate
migration_group: HEUMG
label: 'User IP Migration'
source:
  plugin: tUserIpsMigrate
process:
  bundle:
    plugin: default_value
    default_value: user
  deleted: deleted
  entity_id:
    plugin: migration_lookup
    migration: UserMigrate
    source: user_id
  revision_id:
    plugin: migration_lookup
    migration: UserMigrate
    source: user_id
  langcode:
    plugin: default_value
    default_value: en
  delta: delta
  field_ip_address_ipv6:
    plugin: default_value
    default_value: 0
  field_ip_address_ip_from: ipFrom
  field_ip_address_ip_to: ipTo
destination:
  plugin: field_ip_address
  migration_dependencies:
    required:
      - user_migrate

我还发现 GetIds() 函数对于确定从源到目标的映射非常重要,并且在制作迁移映射表时被迁移系统使用。

扩展 sqlBase 类,我有一个查询来提取迁移所需的数据,它将使用来自不同表用户和 ipaddresses 的 2 个键。所以我的源 getIds() 函数看起来像这样......

 /**
  * {@inheritdoc}
  */
 public function getIds() {
   return [
     'user_id' => [
       'type'  => 'integer',
       'alias' => 'slc',
     ],
     'siteLicense_id' => [
       'type' => 'integer',
       'unsigned' => FALSE,
     ],
   ];
 }

...而我的目的地 getIds 最终变成了这样...

  /**
   * {@inheritdoc}
   */
  public function getIds() {
    return [
      'entity_id' => [
        'type' => 'integer',
        'unsigned' => FALSE,
      ],
      'deleted' => [
        'type' => 'integer',
        'size' => 'tiny',
      ],
      'delta' => [
        'type' => 'integer',
        'unsigned' => FALSE,
      ],
      'langcode' => [
        'type' => 'string',
        'max_length' => 32,
        'is_ascii' => TRUE,
      ],
    ];
  }

定义了上述 getIds() 后,您将在运行 drush 命令后创建一个新表,例如“drush migrate:status”。

表“migrate_map_”+您的迁移 ID 或在我的情况下为 migrate_map_useripsmigrate 是使用 source_id_hash、sourceid1、sourceid2、destid1、destid2、destid3、destid4、source_row_status、rollback_status、last_imported 和 hash 字段创建的。源和目标字段映射到上面定义的 getId,这就是迁移系统如何跟踪从这个特定迁移运行的所有迁移。其他迁移将有自己的表。

至于目标插件本身,我必须基于扩展 DestinationBase 类制作自己的目标插件。

扩展 DestinationBase 需要您定义 3 个函数的内部结构,即 import、getIds 和 fields。我在上面介绍的 GetIds 和字段就像在 SQL 源插件中定义字段一样。导入是您的目标插件将源数据保存到目标的方式。就我而言,我使用了这样的插入查询......

  /**
   * {@inheritdoc}
   */
  public function import(Row $row, array $old_destination_id_values = []) {
    $bundle                   = $row->getDestinationProperty('bundle');
    $deleted                  = $row->getDestinationProperty('deleted');
    $entity_id                = $row->getDestinationProperty('entity_id');
    $revision_id              = $row->getDestinationProperty('revision_id');
    $langcode                 = $row->getDestinationProperty('langcode');
    $delta                    = $row->getDestinationProperty('delta');
    $field_ip_address_ipv6    = $row->getDestinationProperty('field_ip_address_ipv6');
    $field_ip_address_ip_from = $row->getDestinationProperty('field_ip_address_ip_from');
    $field_ip_address_ip_to   = $row->getDestinationProperty('field_ip_address_ip_to');

    $result = $this->con->insert('user__field_ip_address')
  ->fields([
        'bundle'                   => $bundle,
        'deleted'                  => $deleted,
        'entity_id'                => $entity_id,
        'revision_id'              => $revision_id,
        'langcode'                 => $langcode,
        'delta'                    => $delta,
        'field_ip_address_ipv6'    => $field_ip_address_ipv6,
        'field_ip_address_ip_from' => $field_ip_address_ip_from,
        'field_ip_address_ip_to'   => $field_ip_address_ip_to,
      ])
      ->execute();

    return [
      'entity_id' => $entity_id,
      'deleted'   => $deleted,
      'delta'     => $delta,
      'langcode'  => $langcode,
    ];

  }

返回值应该与目标 getIds() 函数中定义的字段相同,并且顺序相同。

这可能不是编写目标插件的最理想方法,但它确实有效。


推荐阅读