Як програмно видалити поле з вузла?


16

Як можна видалити поле з вузла програмно? У мене є міграція, hook_update_Nяка переміщує вміст із поля aa у користувацьку таблицю. Після цієї міграції я хочу видалити поле в тій самій функції.

Чи є якісь API поля, які обслуговують видалення полів?

Редагування, рішення : Оскільки у відповідях відсутній фактичний код, ось що я зробив для переміщення полів від користувачів $ у власні записи та згодом видалення поля з бази даних;

function my_module_update_7005(&$sandbox) {
  $slice = 100;
  //Fetch users from database;
  if (!isset($sandbox['progress'])) {
    $sandbox['progress'] = 0;
    $sandbox['current_uid'] = 0;
    // We'll -1 to disregard the uid 0...
    $sandbox['max'] = db_query('SELECT COUNT(DISTINCT uid) FROM {users}')->fetchField() - 1;
  }
  if (empty($users)) {
    $sandbox["current_uid"] += $slice;
  }
  $users = db_select('users', 'u')
    ->fields('u', array('uid', 'name'))
    ->condition('uid', $sandbox['current_uid'], '>')
    ->range(0, $slice)
    ->orderBy('uid', 'ASC')
    ->execute();
  //Loop trough users;
  foreach ($users as $user) {
    $foo = new Foo();
    // Warning: drupal's fields return mixed values; e.g. NULL versus an int.
    $foo->debits = (int) $user->user()->field_credits["und"][0]["value"];
    $foo->save();

    $sandbox['progress']++;
    $sandbox['current_uid'] = $user->uid;
  }

  $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);

  // Remove the field.
  field_delete_field("field_credits"); //note that the name for Foo is field_foo
  field_purge_batch($sandbox['max']+1);//Drupal seems to have an offbyone problem.
}

Відповіді:


29

field_delete_field($field_name)позначатиме $field_nameдля видалення наступний цикл запуску.

Ви можете використовувати field_purge_batchдля видалення, якщо ви не хочете робити це під час запуску cron.

EDIT: field_delete_field() слід використовувати, коли вам також потрібно видалити поле з інших пакетів. Якщо ви хочете видалити поле лише з певного пакету, вам слід скористатися, field_delete_instance()як згадував @Clive.


4
Обережно, що також буде видалено поле з будь-яких інших пакетів, до яких він може бути приєднаний :) Добре знати, field_purge_batchхоча
Clive

@Clive: правильно, він видалить з поля всі форми. Дякую, що виправили :) Відповідь я відредагував.
AjitS

Я хотів повністю видалити поле, тобто з усіх пакетів. Але попередження добре. Спасибі.
berkes

1
field_delete_instance () - це шлях.
Райан Маквей

field_purge_batch () фактично видалить стільки елементів поля, скільки розмір пакета, який передається йому. Це може допомогти, коли в полі є лише кілька елементів, так що щоб повністю позбутися екземпляра поля, вам не потрібно буде чекати крона, щоб очистити його. Якщо у вас багато значень у полі, не спокушайтесь збільшувати розмір партії занадто високий ("партія" в імені не означає, що вона буде робити якусь партію сама, це просто означає, що вона робить одну партію стільки предметів, скільки ви просите їх); у вас може виникнути пам'ять PHP або часові межі.
Блок Еельке

24

Щоб видалити поле з певного пакета, ви можете використовувати field_delete_instance()

Позначає екземпляр поля та його дані для видалення.

Приклад:

function my_module_update_7001() {
  if ($instance = field_info_instance('node', 'field_name', 'page'))  {
    field_delete_instance($instance, TRUE);
    field_purge_batch(1);
  }
}

Щоб повністю видалити поле з системи, ви можете використовувати field_delete_field()

Позначає поле та його екземпляри та дані для видалення.

Приклад:

function my_module_update_7001() {
  field_delete_field('field_name');
  field_purge_batch(1);
}

Поля / екземпляри позначені лише для видалення, дані фактично будуть очищені під час наступних запусків хронів. Щоб його очистити вручну, виконайте такі дії:

field_purge_batch(1);

1
Під час виклику field_delete_field()та field_purge_batch()роботи він зберігає записи у field_config_instanceта field_config. Чому так?
berkes

Я не дуже розумію, чому виклик field_purge_batch зі значенням 1 позбудеться всіх польових даних. Якщо я правильно розумію код, він отримує дані поля для сутностей $ batchsize і залишає їх при цьому (тобто не рекурсивно викликає функцію або що-небудь інше); Здавалося б, абонент повинен перевірити, чи немає всіх даних, а якщо ні, продовжуйте телефонувати у функцію. Але, можливо, я принципово щось не розумію.
Eelke Blok

Насправді цей коментар у field_ui.admin.inc пояснює це: // Поля очищені на cron. Однак модуль поля запобігає відключенню модулів // коли введені ними типи полів використовуються в полі до повного // очищення. У випадку, якщо поле має мінімальний вміст або його немає, один виклик // to field_purge_batch () видалить його з системи. Назвіть це за допомогою // низького ліміту пакетів, щоб уникнути необхідності адміністраторам чекати запуску cron при видаленні екземплярів, що відповідають цим критеріям.
Eelke Blok

@Clive, я вважаю, що ти ради радиш майже неявно, але я не можу зрозуміти, як дивно мені здається, що я маю декларацію в умовах if. Це цілеспрямовано? Я маю на увазі $instance = field_info_instance('node', 'field_name', 'page'). Чи не натомість це має бути, $instance = field_info_instance('node', 'field_contact', 'job');а потім кинути оператор if?
cdmo

1
@cdmo це називається "призначення в умові", і так, у нього є проблеми . Але ядро ​​Drupal використовує його вільно, навіть в останній версії, тому має принаймні прецедент. Якщо чесно, це було 5 років тому, і я зараз трохи мудріший, я його або не використовую, або якщо з якоїсь причини я збираюся, я завершую завдання (наприклад, if ( ($foo = $bar) ) {так що наміри очевидні та потенційні помилка обмежена. Оператор if необхідний, тому field_delete_instanceщо не перевіряє на null
Clive

5

Щоб відповісти на питання @berkes:

field_delete_field()дійсно позначає поле для видалення, викликаючи його очищення при наступному запуску хронів. Однак він залишає дані field_config_instanceпро поле, що випало. Запуск cron або field_purge_batch()не видалить ці дані з field_config_instanceтаблиці, навіть якщо для поля видаленого стовпця встановлено значення 1.

Для мене з використанням field_delete_instance()подальшого field_purge_batch()для кожного очищеного поля працювали - миттєво видаляючи як поле з бази даних (не вимагаючи cron), так і очищаючи field_config_instanceтаблицю будь-яких даних про поле (для видаленого поля).

Ось рішення:

/**
 * Implements hook_uninstall().
 */
function hook_uninstall() {
  // Delete all fields for all xyz entity bundles.

  // Retrieve all bundles for an entity.
  $bundles = field_info_bundles('XYZ'); // The name of your entity type, for example, 'node'.
  foreach ($bundles as $bundle => $properties) {

    // Retrieve all the fields for a given bundle.
    $instances = field_info_instances('XYZ', $bundle);
    foreach ($instances as $instance) {
      field_delete_instance($instance, TRUE);
      field_purge_batch(1);
    }
  }
}

Ви зверніть увагу TRUEна field_delete_instance(), як це вказує на те, що API поле повинен виконувати роботи з очистки.


Як користуватися цим кодом? Я хочу видалити поле заголовка із типу вмісту
Umair,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.