3

I have two content types on my site and I just deleted all the nodes using $node->delete().

For one of the content types, I noticed that the node body fields did not get deleted, nor did one of the custom fields I made for the content type. All the fields for my other content type were deleted .

So I researched and found the field_purge_field() function. I am not sure how to actually use the function, which is defined as function field_purge_field(FieldConfigInterface $field).
Can someone describe how I would actually load a field and then delete it in this manner (or in a better manner)?

Could I just truncate the tables?

5 Answers 5

5

field_purge_field() is described as follows:

This function assumes all data for the field has already been purged and should only be called by field_purge_batch().

On Drupal, fields are effectively removed during cron tasks; in fact, field_purge_batch() is called from field_cron(), the implementation of hook_cron() done from the Field module. There is no need for you to call neither field_purge_field() nor field_purge_batch().

If you want to write code to purge fields for a node bundle, that code would be similar to the following one. (See the notes after the code, thought.)

  $properties = array(
    'entity_type' => 'node',
    'bundle' => 'Your bundle (a.k.a. content type)',
    'include_deleted' => TRUE,
  );

  $entity_manager = \Drupal::entityTypeManager();

  $fields = $entity_manager->getStorage('field_config')->loadByProperties($properties);

  $info = $entity_manager->getDefinitions();
  foreach ($fields as $field) {
    $entity_type = $field->getTargetEntityTypeId();

    // Proceed only if the module implementing the entity has not been uninstalled already.
    if (isset($info[$entity_type])) {
      $entity_manager->getStorage($entity_type)->purgeFieldData($field, 100);
      field_purge_field($field);
    }
  }

Notes

  • Purging the fields is thought to be ran during cron tasks; that is why Drupal::entityManager()->getStorage()->purgeFieldData() requires the batch size as argument. I used a value of 100, which would possibly allow the code to purge all the fields for that content type, but it could also cause a PHP timeout error. It would be better to run the code from PHP CLI, in order to avoid any execution time out.
  • You should not need to use this code; in most of the cases, you should execute the cron tasks (which is when Drupal purges the fields of a deleted bundle), or use Drush to purge the fields, either running hook_cron() with it, or executing a specific Drush command (if it exists).

As for truncating the tables, that is the wrong way to proceed. It would not allow Drupal and third-party modules to delete the data they have for the fields; even if you know which tables Drupal uses, you could forget a table used by third-party modules.

4
  • Thanks for this info. Where does $fields come from? Is it the output of the loadByProperties() function? Commented Oct 11, 2015 at 18:23
  • Yes, it is. I forgot a part while replacing a function used by Drupal code.
    – avpaderno
    Commented Oct 11, 2015 at 18:27
  • what about locked fields, I need to delete just one field that is locked, I tried that solution but i didn't catch the field to delete Commented Apr 27, 2016 at 6:29
  • @MohammedGomma It is probable that locked fields cannot be deleted, so you cannot even purge them.
    – avpaderno
    Commented Sep 28, 2018 at 7:40
5

The updated version for Drupal 8.3.x using non deprecated functions:

/**
 * Removes field_MY_FIELD_NAME.
 */
function MYMODULE_update_8001() {
  /* @var $entityFieldManager Drupal\Core\Entity\EntityFieldManager */
  $entityFieldManager = Drupal::service('entity_field.manager');

  $fields = $entityFieldManager->getFieldDefinitions('ENTITY_TYPE', 'BUNDLE');

  if (isset($fields['field_MY_FIELD_NAME'])) {
    $fields['field_MY_FIELD_NAME']->delete();
  }
}

Replace the following:

  1. ENTITY_TYPE by the entity type, e.g.: 'taxonomy_term', 'node'...
  2. BUNDLE by the bundle, e.g.: 'article', 'tags'...
  3. field_MY_FIELD_NAME by the field machine name, e.g.: 'field_description'...
4
  • Thank you, this actually deleted the field instances for me. I don't know why purge_field didn't work, maybe it's because I'm using a custom entity? Commented Aug 23, 2017 at 14:52
  • The delete() method is undefined in Drupal 8.6 Commented Jan 15, 2019 at 19:00
  • The delete() function is still here, in EntityInterface. You have to type-hint $fields to something like FieldConfigInterface[] to help your IDE to find the delete() function. api.drupal.org/api/drupal/…
    – Dakwamine
    Commented Jul 28, 2020 at 23:11
  • Out of the box Drupal should already delete a field and purge all of its data when doing so via a config import (e.g. drush cim). This was implemented in 2014 drupal.org/project/drupal/issues/2198429. So the above code should only be needed if that approach failed for some reason.
    – derhasi
    Commented Jan 8, 2022 at 18:30
1

The following will delete content and config of a field in all places used on the same entity type. NOTE: in D7 fields could be used across entity types (i.e. same field used on different bundles of same entity type) but in D8, this is not allowed:

use Drupal\field\Entity\FieldStorageConfig;
FieldStorageConfig::loadByName(ENTITY_TYPE_NAME, FIELD_NAME)->delete();

As with the other methods above, this will result in field remnants being left behind in the key_value and cachetags tables. CRON runs will remove remnants from the key_value table but I have not yet found a way to remove remnants from the cachetags table (short of simply using direct db calls).

[EDIT] I stated that field remnants from key_value table would be removed during CRON; but in fact this only occurs if there had been data in that field. Not sure why this is different but likely a core bug.

0

I found this code for drupal 8 that worked very good for me here https://gist.github.com/jacerider/78b926acbb201666a0fc3a1f8102cb44

This empty the field, them remove field from bundle

I just added in a hook_update_N() https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension%21module.api.php/function/hook_update_N/8.2.x

use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;

$bundles = ['user'];

$fields['user_picture'] = [
  'entity_type' => 'user',
];

foreach ($bundles as $bundle) {
  foreach ($fields as $field_name => $config) {
    $field = FieldConfig::loadByName($config['entity_type'], $bundle, $field_name);
    if (!empty($field)) {
      $field->delete();
    }
  }
}

foreach ($fields as $field_name => $config) {
  $field_storage = FieldStorageConfig::loadByName($config['entity_type'], $field_name);
  if (!empty($field_storage)) {
    $field_storage->delete();
  }
}
0

On Drupal 8 we had a lot of issues after uninstalling the domain module.

We solved this with an install file

@file my_module.install

/**
 * Implements hook_update_N().
 */
function my_module_update_8800(&$sandbox) {
  /** @var \Drupal\Core\Field\DeletedFieldsRepositoryInterface $deleted_fields_repository */
  $deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
  $fields = $deleted_fields_repository->getFieldDefinitions();
  foreach ($fields as $field) {
    field_purge_field($field);
  }
}

Hope this helps someone.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.