Drupal - 从 table 和 creating/updating 现有术语导入带有迁移模块的分类法
Drupal - Importing a taxonomy with migrate module from a table and creating/updating existing terms
我需要从我加载到数据库中的源将术语列表导入到我的分类中。
问题是我的网站上已经有了这个分类法(加载时没有迁移),其中包含在其他内容中引用的术语,所以我必须保留现有术语并更新它们或创建新术语。
为了 link 我的分类来源和现有分类,我为每个术语都有一个唯一的代码,因此我在我的词汇表中添加了一个代码字段并为每个现有术语填充它。
我目前可以使用当前的迁移创建和更新术语 class,但如果我在网站上的术语名称与我的源中的术语名称不同,导入将创建一个新术语而不是更新它的名称,即使代码是相同的。
这是我的迁移 Class :
class TotoMigration extends Migration {
private $list_term = array();
public function __construct($arguments) {
parent::__construct();
$this->softDependencies = array('TotoParent');
// get data from the custom table containing the new terms to create or update
$query = db_select('toto', 'f')
->fields('f', array(
'CODE', // code
'LIBLONG', // name
'PARENT', // parent
)
);
$this->source = new MigrateSourceSQL($query);
$this->destination = new MigrateDestinationTerm('toto_tax');
$this->map = new MigrateSQLMap($this->machineName,
array(
'CODE' => array('type' => 'varchar',
'length' => 5,
'not null' => TRUE,
'description' => 'Code',
)
),
MigrateDestinationTerm::getKeySchema()
);
$this->addFieldMapping('name', 'LIBLONG');
$this->addFieldMapping('field_code', 'CODE');
$this->addFieldMapping('parent', 'PARENT')
->arguments(array('source_type' => 'tid'))
->sourceMigration('TotoParent');
// create a list of existing toto terms with code => tid
$list_term = db_query("select fc.field_code_value, ttd.tid
from taxonomy_term_data ttd
left join taxonomy_term_hierarchy tth on tth.tid=ttd.tid
left join field_data_field_code fc on fc.entity_id = ttd.tid
where ttd.vid=10
and tth.parent!=0;")->fetchAllKeyed();
}
public function prepareRow($row) {
// Always include this fragment at the beginning of every prepareRow()
// implementation, so parent classes can ignore rows.
if (parent::prepareRow($row) === FALSE) {
return FALSE;
}
// if the destination is not mapped in migrate we tell him where to go
if (!isset($row->migrate_map_destid1) && isset($list_term[$row->CODE])) {
$row->migrate_map_destid1 = $list_term[$row->CODE];
}
}
}
然后我使用 drush(和 --update 选项)加载导入。
我一定是遗漏了什么,如果有人知道,欢迎提供。
经过多次尝试,问题在于模块 Migrate 不支持在同一迁移中创建内容和更新内容 class(我什至读过它有时会声称更新内容但什么都不做).
所以解决方案很简单,创建 2 classes :
- 一个用于创建内容
- 一个用于更新内容
您的创建 class 将是相同的。
您的更新 class 需要将 systemeOfRecord 设置为 DESTINATION :
$this->systemOfRecord = Migration::DESTINATION;
所以它知道只更新而不是重新创建内容,它将保持当前字段未映射并更新不属于 MigrateSQLMap 的字段映射:
$this->map = new MigrateSQLMap($this->machineName,array(...));
棘手的部分是找到相应的 nid/tid 内容,以便您可以将其映射到导入的数据,然后分离用于更新或创建内容的数据。
我需要从我加载到数据库中的源将术语列表导入到我的分类中。 问题是我的网站上已经有了这个分类法(加载时没有迁移),其中包含在其他内容中引用的术语,所以我必须保留现有术语并更新它们或创建新术语。
为了 link 我的分类来源和现有分类,我为每个术语都有一个唯一的代码,因此我在我的词汇表中添加了一个代码字段并为每个现有术语填充它。
我目前可以使用当前的迁移创建和更新术语 class,但如果我在网站上的术语名称与我的源中的术语名称不同,导入将创建一个新术语而不是更新它的名称,即使代码是相同的。
这是我的迁移 Class :
class TotoMigration extends Migration {
private $list_term = array();
public function __construct($arguments) {
parent::__construct();
$this->softDependencies = array('TotoParent');
// get data from the custom table containing the new terms to create or update
$query = db_select('toto', 'f')
->fields('f', array(
'CODE', // code
'LIBLONG', // name
'PARENT', // parent
)
);
$this->source = new MigrateSourceSQL($query);
$this->destination = new MigrateDestinationTerm('toto_tax');
$this->map = new MigrateSQLMap($this->machineName,
array(
'CODE' => array('type' => 'varchar',
'length' => 5,
'not null' => TRUE,
'description' => 'Code',
)
),
MigrateDestinationTerm::getKeySchema()
);
$this->addFieldMapping('name', 'LIBLONG');
$this->addFieldMapping('field_code', 'CODE');
$this->addFieldMapping('parent', 'PARENT')
->arguments(array('source_type' => 'tid'))
->sourceMigration('TotoParent');
// create a list of existing toto terms with code => tid
$list_term = db_query("select fc.field_code_value, ttd.tid
from taxonomy_term_data ttd
left join taxonomy_term_hierarchy tth on tth.tid=ttd.tid
left join field_data_field_code fc on fc.entity_id = ttd.tid
where ttd.vid=10
and tth.parent!=0;")->fetchAllKeyed();
}
public function prepareRow($row) {
// Always include this fragment at the beginning of every prepareRow()
// implementation, so parent classes can ignore rows.
if (parent::prepareRow($row) === FALSE) {
return FALSE;
}
// if the destination is not mapped in migrate we tell him where to go
if (!isset($row->migrate_map_destid1) && isset($list_term[$row->CODE])) {
$row->migrate_map_destid1 = $list_term[$row->CODE];
}
}
}
然后我使用 drush(和 --update 选项)加载导入。 我一定是遗漏了什么,如果有人知道,欢迎提供。
经过多次尝试,问题在于模块 Migrate 不支持在同一迁移中创建内容和更新内容 class(我什至读过它有时会声称更新内容但什么都不做).
所以解决方案很简单,创建 2 classes :
- 一个用于创建内容
- 一个用于更新内容
您的创建 class 将是相同的。
您的更新 class 需要将 systemeOfRecord 设置为 DESTINATION :
$this->systemOfRecord = Migration::DESTINATION;
所以它知道只更新而不是重新创建内容,它将保持当前字段未映射并更新不属于 MigrateSQLMap 的字段映射:
$this->map = new MigrateSQLMap($this->machineName,array(...));
棘手的部分是找到相应的 nid/tid 内容,以便您可以将其映射到导入的数据,然后分离用于更新或创建内容的数据。