1

Let say, I have 2 nodes.
In first node, I add a reference to an existing node, e.g. Test node [nid:2]; I delete the referenced node. When I edit the first node,the reference field shows [nid:2].

How can I make that reference field empty, once the referenced node is deleted?

1
  • Which version of Drupal are you using ? Mar 15, 2017 at 18:57

2 Answers 2

1

Try using Reference Delete module..

Project page says

Deletes values in reference fields created with Entity Reference or References when the referenced entity is deleted.

1
  • Thanks Anil, Is there any way to remove from our custom code...I just want to finish with short code....
    – Srinu
    Aug 26, 2014 at 10:23
0

If you want to add code for that purpose to a custom module you already have, then you can use the code the Reference Delete module is using as guide.

In short, the code used in the 7.x-1 branch:

  • When an entity is deleted, it adds its ID and type to a queue
  • During cron task, delete the reference to the deleted entities found on the tables used from the reference fields

The first part is done implementing hook_entity_delete(). For the second part, this is the relevant code used from that module.

/**
 * Returns an array of fields, filtered by module.
 */
function _reference_delete_get_reference_fields($module) {
  $fields = field_info_field_map();

  $reference_fields = array();

  foreach ( $fields as $field_name => &$properties ) {
    $properties = field_info_field($field_name);

    if ($properties['module'] == $module) {
      $reference_fields[$field_name] = $properties;
    }
  }

  if ( !empty($reference_fields) ) {
    return $reference_fields;
  }
}

/**
 * Implements hook_reference_delete_delete_references().
 */
function entityreference_reference_delete_delete_references($entity_id, $type) {
  $module = 'entityreference';

  if ( $fields = _reference_delete_get_reference_fields($module) ) {
    foreach ( $fields as $field_name => $properties ) {
      // Acts only if the target entity is of the same type of the entity that's being deleted
      if ( $properties['settings']['target_type'] == $type ) {
        $tables = reset($properties['storage']['details']);

        foreach ( $tables as $table ) {
          $keys = array_keys($table);
          $table_name = reset($keys);
          $column_name = $table[$table_name]['target_id'];

          db_delete($table_name)
          ->condition($column_name, $entity_id, '=')
          ->execute();

          watchdog('reference_delete', 'Deleted all references to entity %entity_type #!entity_id from table !table', array('%entity_type' => $type, '!entity_id' => $entity_id, '!table' => $table_name), WATCHDOG_NOTICE);
        }
      }
    }
  }
}

/**
 * Implements hook_reference_delete_delete_references().
 */
function references_reference_delete_delete_references($entity_id, $type) {
  switch ($type) {
    case 'node' :
      $module = 'node_reference';

      if ( $fields = _references_reference_delete_make_table_names($module) ) {
        foreach ( $fields as $field => $tables ) {
          foreach ( $tables as $table ) {
            db_delete($table)
              ->condition($field . '_nid', $entity_id, '=')
              ->execute();

            watchdog('reference_delete', 'Deleted all references to entity %entity_type #!entity_id from table !table', array('%entity_type' => $type, '!entity_id' => $entity_id, '!table' => $table_name), WATCHDOG_NOTICE);
          }
        }
      }
    break;

    case 'user' :
      $module = 'user_reference';

      if ( $fields = _references_reference_delete_make_table_names($module) ) {
        foreach ( $fields as $field => $tables ) {
          foreach ( $tables as $table_name ) {
            db_delete($table_name)
              ->condition($field . '_uid', $entity_id, '=')
              ->execute();

            watchdog('reference_delete', 'Deleted all references to entity %entity_type #!entity_id from table !table', array('%entity_type' => $type, '!entity_id' => $entity_id, '!table' => $table_name), WATCHDOG_NOTICE);
          }
        }
      }
    break;
  }
}

/**
 * Creates table names (used only for References).
 */
function _references_reference_delete_make_table_names($module) {
  if (isset($module)) {
    $fields = _reference_delete_get_reference_fields($module);

    if ( count($fields) ) {
      $tables = array();
      foreach ( $fields as $field ) {

        $tables[$field] = array('field_data_' . $field, 'field_revision_' . $field);
      }

      return $tables;
    }
  }
}

hook_reference_delete_delete_references() is a hook used from that module. You don't need to implement it, but use that code to write a function, or a hook, for example hook_cron() or the worker callback of a queue, in the case you want to follow the same approach used from that module.

I would rather implement hook_entity_delete() and delete any reference to the deleted node from the tables used from the reference module being used.

1
  • When I have time, I will write an example implementation of hook_entity_delete() with code taken from the Reference Delete module.
    – apaderno
    Mar 16, 2017 at 13:28

Your Answer

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

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