Можно ли программно изменить столбец vid термина в базе данных?

8

Мне нужно переместить некоторые термины из одного словаря в другой, сохранив все их данные: переводы, псевдонимы и ссылки на узлы.

Допустимо ли изменять vidзначение столбца непосредственно в базе данных? Термины не имеют иерархических отношений, которые должны быть обработаны.

мольфар
источник

Ответы:

11

База данных

В Drupal можно многое сделать, просто выполняя SQL-запросы, либо через Drupal, либо внешне. Как правило, вы никогда не хотите использовать этот подход. В некоторых случаях это может работать просто отлично, но в большинстве случаев нет причин делать это таким образом.

API

Drupal имеет богатый API, это верно для Drupal 6, 7 и 8, так как они всегда были ключевой функцией в Drupal. В вашем конкретном примере вы можете использовать taxonomy_term_loadи taxonomy_term_saveдля облегчения обновления термина. Делая это таким образом, вы можете редактировать любую часть данных, включая vid. Просто потому, что вы делаете это с помощью API, выполнение запрещенных вещей не будет работать автоматически, но вероятность того, что все будет хорошо, значительно улучшится.

В этом конкретном примере API не делает ничего, что обязательно необходимо. Он устанавливает некоторые внутренние данные для термина и вызывает модуль перехвата букв, который был обновлен.

Следует помнить, что все может сломаться, если термин, который вы хотите изменить, является частью иерархии. Вещи могут также сломаться для узлов, ссылающихся на термин, если в поле не разрешено ссылаться на термины в новом словаре.

миграция

Миграция данных является пуленепробиваемым решением, и если у вас нет огромного набора данных, его можно разработать и выполнить довольно легко. Идея состоит в том, чтобы создать новый термин и перенести контент, который вы хотите перенести, а затем удалить старый термин. Как пример обновления, пример кода может выглядеть так:

/**
 * Put in modules .install file, replace xxxx with 7000 or higher
 */
function MODULE_NAME_update_XXXX(&$sandbox) {
  $term = taxonomy_term_load(CONSTANT_WITH_TID);
  $new_term = clone $term;
  unset($new_term->tid);
  unset($new_term->tid);
  $new_term->vid = CONSTANT_WITH_VID;
  taxonomy_term_save($term);
  // Find all nodes we want to update and update them.
  // If there is a lot of nodes, can use $sandbox to make this a batch job.
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'node')
    ->fieldCondition('field_which_is_term_reference', 'tid', $term->tid);
  $result = $query->execute();
  foreach (node_load_multiple(array_keys($result['node'])) as $node) {
    $node->field_which_is_term_reference[LANGUAGE_NONE][0]['tid'] = $term->tid;
    node_save($node);
  }
  // Migration all done - delete the old term.
  taxonomy_term_delete($term->tid);
}

Обратите внимание, что приведенный выше код является чистым примером кода, написанным наизусть. Может иметь синтаксическую ошибку или другие ошибки и делает много предположений. Это просто, чтобы проиллюстрировать идею и продемонстрировать, что миграция может не иметь большого значения.

googletorp
источник
4

Это не рекомендуется делать прямые изменения базы данных при работе с Drupal. Но да, если мы знаем , где все это может повлиять и сделать необходимые изменения , соответственно, это нормально , чтобы сделать прямые изменения в базе данных. Потому что в этом случае это невозможно через пользовательский интерфейс. ПРИМЕЧАНИЕ. Если у вас есть узлы, связанные с термином, вам также придется обрабатывать его вручную.

Посмотрите эту ссылку, которая объясняет, как мы можем изменить словарный запас в Drupal 7: изменить словарь таксономического термина в Drupal 7, используя базу данных .

Yogesh
источник
Единственная проблема, которую я вижу в этом - это то, что если в случае есть поля, связанные с термином с некоторыми значениями, и вы меняете его vid, то данные, хранящиеся в поле, будут потеряны.
Ашиш Дейнап
Да, именно поэтому я также упомянул, что, если есть какие-либо узлы, которые необходимо подключить, то с ними тоже нужно работать .
Йогеш
Но какие-либо данные также привязаны к термину через vid? не только тид ключом?
Мольфар
Нет, любые данные, связанные с термином, относятся к tid. vid используется для ссылки только на словарный идентификатор, больше ничего.
Йогеш
4

Я бы не рекомендовал менять этот термин так, как вы описали его в своем вопросе. Вместо этого я бы использовал альтернативный подход для достижения аналогичного результата (в указанном порядке), что более подробно описано ниже.

Шаг 1 - Начните использовать новый термин в будущих обновлениях узла

Создайте новое поле термина таксономии, чтобы «с этого момента» любые будущие обновления узлов (или создаваемые новые узлы) использовали это новое поле. Я предполагаю, что эти термины используются для узлов (если вы используете его для какого-либо другого типа сущности, например, пользователей и т. Д.), Такой же подход можно использовать и для этих сущностей.

Используйте модуль « Правила » для создания правила следующим образом:

  • Правила события: before saving content.
  • Правила условий:
    • entity has field, с полем = старое поле.
    • И НЕ ( entity has fieldс полем = новое поле).
  • Правила Действие: set Drupal messageсодержит некоторые инструкции о том, что старое поле должно быть очищено, а новое поле должно содержать соответствующие значения.

Шаг 2 - Используйте правила, чтобы ускорить процесс

Очевидно, что подход на шаге 1 займет «некоторое» время, если это нужно сделать вручную, по 1 узлу за раз. Но с помощью Views (для создания списка аналогичных узлов, подлежащих обновлению) и VBO (для массового обновления таких списков) вы могли бы (должны!) Значительно ускорить этот процесс.

Особенно, если бы вы использовали Правила для создания настраиваемой групповой операции для такого представления VBO, как объясняется в ответе на вопрос « Как использовать Правила для создания настраиваемой групповой операции для представления VBO? ». Вот прототип компонента Rules, который должен помочь реализовать такую ​​пользовательскую массовую операцию (в формате Export Export):

{ "rules_replace_a_term_field_by_another_term_field" : {
    "LABEL" : "Replace a term field by another term field",
    "PLUGIN" : "rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules" ],
    "USES VARIABLES" : { "node" : { "label" : "Node", "type" : "node" } },
    "IF" : [
      { "entity_has_field" : { "entity" : [ "node" ], "field" : "field_sample_tags" } },
      { "entity_has_field" : { "entity" : [ "node" ], "field" : "field_demo_tags" } },
      { "data_is" : { "data" : [ "node:field-demo-tags" ], "value" : "1" } }
    ],
    "DO" : [
      { "data_set" : { "data" : [ "node:field-sample-tags" ], "value" : "31" } },
      { "drupal_message" : { "message" : "Term updated in node with id = [node:nid]" } }
    ]
  }
}

Еще некоторые подробности, чтобы объяснить вышеупомянутый прототип:

  • Он использует узел в качестве параметра.
  • Это Правила Условия:

    • проверьте, имеет ли объект (= узел) поле field_sample_tags.
    • проверьте, имеет ли объект (= узел) поле field_demo_tags.
    • проверьте, соответствует ли значение поля field_demo_tagsтермину, который мы хотим заменить (в этом примере термин имеет id = 1). Обратите внимание, что если это условие не выполняется, действия по правилам выполняться не будут.
  • Это Правила Действия:

    • Установите значение поля field_sample_tagsравным термину с термином id = 31(который является термином во вновь созданном словаре, который соответствует термину в словаре, который должен быть заменен).
    • Отображать сообщение на сайте, как Term updated in node with id = 72, в то 72время как идентификатор узла обновленного узла.

Если хотите, адаптируйте имена машин для имен полей в вышеприведенном прототипе и идентификаторы используемых терминов. Затем импортируйте его на свой собственный сайт (используя пользовательский интерфейс правил) и выполните QA-тестирование, используя ссылку «execute» справа от импортированного компонента Rules (и введите некоторый идентификатор узла, чтобы протестировать его после переключения на «прямой ввод»). режим ", чтобы иметь возможность указать идентификатор узла). Если во время тестирования вы не получили такого Term updated in node ...сообщения, это должно быть потому, что выбранный вами узел не использовал значение термина, указанное в ваших правилах Условие.

Шаг 3 - Используйте VBO как последний штрих

После того, как вы закончите QA-тестирование этого компонента правил из шага 2, создайте VBO-представление узлов, которые нужно обработать, в котором вы обратитесь к прототипу правил выше (или его вариации в соответствии с вашими потребностями).

Преимущество такого подхода

Используя этот подход, вы сводите к минимуму риск внесения несоответствий данных (по сравнению с непосредственным обновлением базы данных) без участия пользовательского кода (вы будете использовать только пользовательский интерфейс Views и Rules UI).

Pierre.Vriens
источник
Вы предполагаете, что представления, VBO и правила уже установлены, в противном случае вам нужно установить 3 модуля для этого решения. Кроме того, «код» конфигурации, который вам нужно реализовать, не менее сложен, чем то, что нужно было бы сделать в хуке обновления. Я хочу сказать, что использование правил и представлений не так просто, как кажется. Также стоит помнить, что, хотя с помощью Views и Rules вы можете создавать практически все, это не всегда хорошая идея.
googletorp
1
Да, действительно: чтобы использовать Views, Rules или VBO, модуль должен быть установлен (+ включен). Но из примерно 990 тыс. Сайтов D7 есть около 810 тыс. Сайтов, которые также имеют просмотры , это более 80%. А для сайтов, у которых нет причины использовать Правила или VBO: эти модули нужны только для такого преобразования (когда они будут выполнены, их можно удалить, если хотите). О простоте: ИМО, это скорее вопрос опыта. Преимущество этого подхода заключается в том, что он требует только навыков создания сайтов (опытный разработчик PHP может быть недоступен / недоступен).
Pierre.Vriens
2

Я знаю, что вы говорите программно, но если вы хотите использовать модуль, вы можете использовать таксономический менеджер

Этот модуль предоставляет мощный интерфейс для управления таксономиями. Словарь отображается в динамическом древовидном представлении, где родительские термины могут быть расширены для перечисления их вложенных дочерних терминов или могут быть свернуты.

Менеджер таксономии имеет следующие операции и ключевые функции:

  • динамическое дерево
  • массовое удаление
  • массовое добавление новых терминов
  • перемещение терминов в иерархиях объединение терминов (с помощью модуля объединения терминов в 7.x)
  • быстрое изменение веса с помощью стрелок вверх и вниз (и сохранение AJAX)
  • AJAX механизированная форма редактирования терминов
  • простой интерфейс поиска
  • CSV Экспорт условий
  • i18n поддержка многоязычных словарей (по языковым терминам)
  • Интерфейс Double Tree для перемещения терминов в иерархиях, добавления новых переводов и переключения терминов между различными словарями
Адриан Сид Альмагер
источник