Eliminare a livello di codice una voce da un campo su un'entità


13

Qual è il modo corretto di eliminare a livello di codice una voce di campo specifica per un campo a più voci da un'entità specifica? (ovvero campi specifici ed entità specifiche, non tipi di campo o istanze e tipi di entità)

Ecco alcune possibilità che ho esaminato che non funzionano:

  • Caricando l'entità con entity_load(), impostando la voce di campo su = null o = array (), quindi salvando con field_attach_update(). È il più vicino che ho trovato ma lascia una voce di campo null zombie nel database che si presenta come una riga vuota sui moduli fino a quando il modulo non viene salvato e hook_field_is_empty()può iniziare ( hook_field_is_empty()è configurato in modo tale che = null o = array () verrà contrassegnato come vuoto).
  • Caricare l'entità con entity_load(), annullare l'inserimento del campo per chiave, quindi salvare con field_attach_update(). Questo sembra non fare nulla - sembra che Drupal interpreta la voce non essere lì come un segno per non modificarlo. (stranamente a volte ottengo anche i timeout di scadenza del tempo di query massimo quando provo questo approccio)
  • field_attach_delete() - è troppo schietto: uccide tutti i campi per l'entità
  • field_purge_data() - migliore, ma ancora troppo schietto: uccide tutte le voci del campo, non quelle specifiche

Quindi, per chiarire, ho un codice che trova (e carica) un'entità che ha un campo con più voci e trova una voce specifica su quel campo che deve essere rimossa. Voglio rimuovere quella voce completamente, senza toccare altre voci o altri campi sull'entità.

Risposte:


24

Se sei in grado di fare affidamento sul modulo API dell'entità , dovresti essere in grado di utilizzare un codice simile al seguente:

// 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);

2
Questo ha funzionato! Grazie, il mio problema con gli zombi è stato ormai sradicato. Alcune note che potrebbero far risparmiare tempo ad altri: avevo bisogno di aggiornare l'entità API a RC2; poiché stavo usando un nome di campo dinamico, la riga non impostata aveva bisogno di parentesi graffe come unset ($ entity -> {$ field_name} [LANGUAGE_NONE] [$ index]); e per evitare un avvertimento ho dovuto racchiudere array_values ​​() in if (! empty (...)) {}
user56reinstatemonica8

Questo funziona anche se vuoi solo cancellare l'intero campo ed evita il temuto "Violazione del vincolo di integrità: la colonna 1048 'field_duty_user_target_id' non può essere nulla"
Darrell Duane,

Molte grazie! ha provato a cambiare il valore del campo tramite node_load, ma non ha funzionato. Quindi cambiare il valore del campo entità in questo modo sicuramente funziona!
Артем Ильин,

1

Ho dovuto fare questo come parte di una pulizia della migrazione di Drupal8.

Dopo alcuni esperimenti, ho scoperto che iterare e quindi usare unset () sul delta potrebbe ucciderlo. Il mio esempio è stato la rimozione di un tag (quindi cerco "target_id", non "valore" come faresti spesso per altri campi.

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

E dopo, se il successo, allora $object->save();


0

Per Drupal 8, per eliminare un campo da un'entità:

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

Questo chiamerà il metodo magico __unset () da 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]);
    }
}

Non dimenticare che, per persistere nelle modifiche, devi chiamare

$entity->save();

Dopo aver apportato tutte le modifiche.


-1

Questo è il modo migliore:

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

-2

l'attuale metodo preferito impiegherebbe entity_metadata_wrapper

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

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

questo è il miglior tutorial sull'EMW che ho visto http://deeson-online.co.uk/labs/programatical-access-field-data-using-entitymetadatawrapper-drupal


questo non ha funzionato. L'ho provato anche così senza fortuna; $ wrapper = entity_metadata_wrapper ('node', $ duty); unset ($ wrapper-> field_duty_user); $ wrapper-> save (); node_save ($ dovere);
Darrell Duane,

1
Il modo corretto sarebbe $ node_wrapped-> field_name-> set (""); quindi $ wrapper-> save ()
chadpeppers il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.