web-dev-qa-db-fra.com

Supprimer par programme une entrée d'un champ sur une entité

Quelle est la bonne façon de supprimer par programme une entrée de champ spécifique pour un champ à entrées multiples d'une entité spécifique? (ce sont des champs et des entités spécifiques, pas des types de champs ou des instances et des types d'entités)

Voici quelques possibilités que j'ai examinées et qui ne fonctionnent pas:

  • Chargement de l'entité avec entity_load(), définition de l'entrée de champ sur = null ou = tableau (), puis enregistrement avec field_attach_update(). C'est le plus proche que j'ai trouvé, mais il laisse une entrée de champ nul zombie dans la base de données qui apparaît comme une ligne vide sur les formulaires jusqu'à ce que le formulaire soit enregistré et que hook_field_is_empty() puisse entrer (hook_field_is_empty() est configuré de telle sorte que = null ou = array () marquera comme vide).
  • Chargement de l'entité avec entity_load(), suppression de l'entrée de champ par touche, puis sauvegarde avec field_attach_update(). Cela semble ne rien faire - il semble que Drupal interprète l'entrée ne pas être là comme un signe pour ne pas la modifier.
  • field_attach_delete() - c'est beaucoup trop brutal: il tue tous les champs de l'entité
  • field_purge_data() - mieux, mais toujours trop brutal: il tue toutes les entrées du champ, pas les entrées spécifiques

Donc, pour clarifier, j'ai un code qui trouve (et charge) une entité qui a un champ qui a plusieurs entrées et trouve une entrée spécifique sur ce champ qui doit être supprimée. Je souhaite supprimer complètement cette entrée, sans toucher aucune autre entrée ni aucun autre champ de l'entité.

13

Si vous êtes en mesure de compter sur le module API d'entité vous devriez pouvoir utiliser un code similaire à ce qui suit:

// Load some entity.
$entity = entity_load_single($entity_type, $id);

// Remove the field value.
unset($entity->field_FIELD_NAME[LANGUAGE_NONE][$index]);

// Reset the array to zero-based sequential keys.
$entity->field_FIELD_NAME[LANGUAGE_NONE] = array_values($entity->field_FIELD_NAME[LANGUAGE_NONE]);

// Save the entity.
entity_save($entity_type, $entity);
24
Clive

J'avais besoin de le faire dans le cadre d'un nettoyage de migration Drupal8.

Après quelques expérimentations, j'ai trouvé que l'itération puis l'utilisation de unset () sur le delta pouvaient le tuer. Mon exemple consistait à supprimer une balise (donc je recherche "target_id", pas "value" comme vous le feriez souvent pour d'autres champs.

/**
 * Removes a term from a field.
 *
 * @return bool
 *   success
 */
private function removeTerm(\Drupal\node\NodeInterface $object, \Drupal\taxonomy\TermInterface $term, $field_name) {
  // Check if tag value exists already.
  // Remember they may be multiples.
  /** @var @var \Drupal\Core\Field\FieldItemList $field_values */
  $field_values = $object->get($field_name);
  foreach ($field_values as $delta => $field_value) {
    if ($field_value->getValue()['target_id'] == $term->id()) {
      unset($field_values[$delta]);
      return TRUE;
    }
  }
  return FALSE;
}

Et après, en cas de succès, alors $object->save();

1
dman

Pour Drupal 8, pour supprimer un champ d'une entité:

$entity = Node::load($nid);
unset($entity->field_name);

Cela appellera la méthode magique __unset () de ContentEntityBase:

public function __unset($name) {
    // Unsetting a field means emptying it.
    if ($this->hasField($name)) {
        $this->get($name)->setValue([]);
    }
    // For non-field properties, unset the internal value.
    else {
        unset($this->values[$name]);
    }
}

N'oubliez pas que, pour conserver vos changements, vous devez appeler

$entity->save();

Après avoir effectué toutes vos modifications.

0