Löschen Sie programmgesteuert einen Eintrag aus einem Feld in einer Entität

13

Wie kann ein bestimmter Feldeintrag für ein Feld mit mehreren Einträgen programmgesteuert aus einer bestimmten Entität gelöscht werden? (Das sind bestimmte Felder und bestimmte Entitäten, keine Feldtypen oder Instanzen und Entitätstypen.)

Hier sind einige Möglichkeiten, die ich untersucht habe und die nicht funktionieren:

  • Laden Sie die Entität mit entity_load(), setzen Sie den Feldeintrag auf = null oder = array () und speichern Sie dann mit field_attach_update(). Es ist das nächste, das ich gefunden habe, aber es hinterlässt einen Zombie-Null-Feldeintrag in der Datenbank, der in Formularen als leere Zeile angezeigt wird, bis das Formular gespeichert wird und hook_field_is_empty()aktiviert werden kann ( hook_field_is_empty()ist so konfiguriert, dass = null oder = array () markiert wird als leer).
  • Laden der Entität mit entity_load(), Deaktivieren des Feldeintrags mit der Taste und Speichern mit field_attach_update(). Dies scheint nichts zu bewirken - es scheint, dass Drupal den Eintrag, der nicht vorhanden ist, als Zeichen interpretiert, um ihn nicht zu ändern. (Seltsamerweise bekomme ich manchmal auch maximale Zeitüberschreitungen beim Abfragen, wenn ich diesen Ansatz versuche.)
  • field_attach_delete() - das ist viel zu stumpf: es löscht alle Felder für die Entität
  • field_purge_data() - Besser, aber immer noch zu stumpf: Es werden alle Einträge des Feldes gelöscht, keine spezifischen Einträge

Zur Verdeutlichung habe ich Code, der eine Entität mit einem Feld mit mehreren Einträgen findet (und lädt) und in diesem Feld einen bestimmten Eintrag findet, der entfernt werden muss. Ich möchte diesen Eintrag vollständig entfernen, ohne andere Einträge oder andere Felder in der Entität zu berühren.

user56reinstatemonica8
quelle

Antworten:

24

Wenn Sie sich auf das Entitäts-API-Modul verlassen können , sollten Sie in der Lage sein, Code ähnlich dem folgenden zu verwenden:

// 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);
Clive
quelle
2
Das hat funktioniert! Danke, mein Zombie-Problem wurde behoben. Ein paar Hinweise, die anderen Zeit sparen könnten: Ich musste die Entity-API auf RC2 aktualisieren. da ich einen dynamischen Feldnamen verwendete, benötigte die nicht gesetzte Zeile geschweifte Klammern wie "nicht gesetzt" ($ entity -> {$ field_name} [LANGUAGE_NONE] [$ index]); und um eine Warnung zu vermeiden, musste ich die array_values ​​() in if (! empty (...)) {}
user56reinstatemonica8
Dies funktioniert auch, wenn Sie nur das gesamte Feld löschen möchten, und umgeht die gefürchtete Verletzung der "Integritätsbedingung: 1048-Spalte 'field_duty_user_target_id' darf nicht null sein"
Darrell Duane
Danke vielmals! hat versucht, den Feldwert über node_load zu ändern, aber es hat nicht funktioniert. Das Ändern des Werts eines Entitätsfelds wie dieses funktioniert also auf jeden Fall!
Артем Ильин
1

Ich musste dies im Rahmen einer Drupal8-Migrationsbereinigung tun.

Nach einigem Experimentieren stellte ich fest, dass das Iterieren und anschließende Verwenden von unset () im Delta dazu führen kann, dass es nicht mehr funktioniert. Mein Beispiel war das Entfernen eines Tags (daher suche ich nach 'target_id' und nicht nach 'value', wie Sie es oft für andere Felder tun würden).

/**
 * 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;
}

Und danach, wenn Erfolg, dann $object->save();

dman
quelle
0

So löschen Sie in Drupal 8 ein Feld aus einer Entität:

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

Dies ruft die magische Methode __unset () von ContentEntityBase auf:

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]);
    }
}

Vergessen Sie nicht, dass Sie anrufen müssen, um Ihre Änderungen beizubehalten

$entity->save();

Nachdem Sie alle Änderungen vorgenommen haben.

Miguel Guerreiro
quelle
-1

Das ist besser so:

> $user = user_load($user->uid); 
> $user_wrp = entity_metadata_wrapper('user', $user);
> $user_wrp->{'field_data_multiple'} = array();
Mike Nguyen
quelle
-2

Die derzeit bevorzugte Methode würde den entity_metadata_wrapper verwenden

$node_wrapped = entity_metadata_wrapper('node', node_load($nid));

unset($node_wrapped->$field_name[$index];

Dies ist das beste Tutorial im EMW, das ich gesehen habe http://deeson-online.co.uk/labs/programatically-access-field-data-using-entitymetadatawrapper-drupal

Dotist
quelle
das hat nicht funktioniert. Ich habe es sogar ohne Glück versucht; $ wrapper = entity_metadata_wrapper ('node', $ duty); unset ($ wrapper-> field_duty_user); $ wrapper-> save (); node_save ($ duty);
Darrell Duane
1
Der richtige Weg wäre $ node_wrapped-> field_name-> set (""); dann $ wrapper-> save ()
chadpeppers