Есть файл для импорта товаров (нод), в котором категория товара указана в виде списка названий категорий и подкатегорий. Для миграции таких терминов из коробки можно использовать следующую конструкцию...
Есть файл для импорта товаров (нод), в котором категория товара указана в виде списка названий категорий и подкатегорий. Например:
Для миграции таких терминов из коробки можно использовать следующую конструкцию (миграция данных в multi-value поля):
$this->addFieldMapping('taxonomy_catalog', 'catalog')->separator(',');
//сообщим Migrate, что мы используем имена терминов, а не tid
$this->addFieldMapping('taxonomy_catalog:source_type')->defaultValue('name');
//если термин не найден по имени, разрешим автоматическое создание термина
$this->addFieldMapping('taxonomy_catalog:create_term')->defaultValue(TRUE);
Во время импорта migrate осуществляет поиск термина по имени, если его нет в словаре, то он автоматически создается.
Плюсы:
- решение из коробки;
Минусы:
- нет иерархии терминов;
- в словаре отсутствуют термины с одинаковыми именами;
Конечно, мы можем на основе нашего файла для импорта нод сделать файл со списком терминов, отдельно импортировать термины и только потом ноды. Если каталог изменится, эти манипуляции придется повторить.
Мы сделаем немного по-другому....
public function __construct($arguments) {
...
$this->addFieldMapping('taxonomy_catalog', 'catalog');
$this->addFieldMapping('taxonomy_catalog:source_type')->defaultValue('tid');
$this->addFieldMapping('taxonomy_catalog:create_term')->defaultValue(TRUE);
}
public function prepareRow($row) {
...
if (isset($row->catalog) && !empty($row->catalog)) {
//для нормальной работы нам нужно знать vid словаря таксономии, в который будут импортироваться термины.
$vocabulary = taxonomy_vocabulary_machine_name_load('catalog');
$vid = $vocabulary->vid;
//Если Вы не хотите постоянно дергать функцию taxonomy_vocabulary_machine_name_load,
//можете вручную указать номер нужного словаря
// $vid = 2;
$row->catalog = _migrate_taxonomy_term_tree($row->catalog, $vid);
}
}
function _migrate_taxonomy_term_tree($namestxt, $vid) {
$names = explode(',', $namestxt);
$tids = array();
foreach ($names as $depth => $name) {
//предварительно очистим заголовок термина
$name = trim(check_plain($name));
//определим родителя
$parent = ($depth > 0) ? $tids[$depth - 1] : 0;
//пробуем найти нужный tid
$query = db_select('taxonomy_term_data', 't');
$query->innerJoin('taxonomy_term_hierarchy', 'th', 't.tid = th.tid');
$query->fields('t', array('tid'));
$query->condition('t.vid', $vid);
$query->condition('t.name', $name);
$query->condition('th.parent', $parent);
$tid = $query->execute()->fetchField();
if ($tid) {
//термин уже в БД
$tids[$depth] = $tid;
}
else {
//нужно создавать термин
$term = array(
'vid' => $vid,
'name' => $name,
'parent' => $parent,
);
$term = (object) $term;
taxonomy_term_save($term);
if ($term->tid) {
$tids[$depth] = $term->tid;
}
else {
$tids[$depth] = 0;
drupal_set_message(t('Query not successful.'), 'error');
}
}
}
//на всякий случай проверим массив и удалим нулевые термины
foreach ($tids as $key => $tid) {
if($tid == 0){
unset($tids[$key]);
}
}
return $tids;
}
К данному решению можно прикрутить кеширование, что бы уменьшить количество запросов к БД. Но мне пока лень этим заниматься :-)
function _migrate_taxonomy_term_tree($namestxt, $vid) {
$names = explode(',', $namestxt);
$namesmd5 = md5($vid . '_' . $namestxt);
$tids = array();
if ($cache = cache_get('migrate_term_tree_' . $namesmd5)) {
$tids = explode(',', $cache->data);
}else{
foreach ($names as $depth => $name) {
$name = trim(check_plain($name));
$parent = ($depth > 0) ? $tids[$depth - 1] : 0;
$query = db_select('taxonomy_term_data', 't');
$query->innerJoin('taxonomy_term_hierarchy', 'th', 't.tid = th.tid');
$query->fields('t', array('tid'));
$query->condition('t.vid', $vid);
$query->condition('t.name', $name);
$query->condition('th.parent', $parent);
$tid = $query->execute()->fetchField();
if ($tid) {
//термин уже в БД
$tids[$depth] = $tid;
}
else {
//нужно создавать термин
$term = array(
'vid' => $vid,
'name' => $name,
'parent' => $parent,
);
$term = (object) $term;
taxonomy_term_save($term);
if ($term->tid) {
$tids[$depth] = $term->tid;
}
else {
$tids[$depth] = 0;
drupal_set_message(t('Query not successful.'), 'error');
}
}
}
foreach ($tids as $key => $tid) {
if($tid == 0){
unset($tids[$key]);
}
}
cache_set('migrate_term_tree_' . $namesmd5, implode(',', $tids), 'cache', time() + 3600);
}
return $tids;
}
Актуально для:
migrate7.x-2.8
- 18.09.2015
- 65 просмотров