Очередной "финт ушами".
Есть файл для импорта товаров (нод), в котором категория товара указана в виде списка названий категорий и подкатегорий. Например:
Для миграции таких терминов из коробки можно использовать следующую конструкцию (миграция данных в 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); } }
И напишем функцию, которая на основе строки с терминами, разделенными запятой, будет возвращать массив с tid.
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
Комментарии
Добавить комментарий