Excluir programaticamente uma entrada de um campo em uma entidade

13

Qual é a maneira correta de excluir programaticamente uma entrada de campo específica para um campo com várias entradas de uma entidade específica? (são campos e entidades específicos, não tipos de campo ou instâncias e tipos de entidade)

Aqui estão algumas possibilidades que examinei e que não funcionam:

  • Carregando a entidade com entity_load(), definindo a entrada do campo como = null ou = array () e salvando com field_attach_update(). É o mais próximo que eu encontrei, mas deixa uma entrada de campo nulo zumbi no banco de dados que aparece como uma linha em branco nos formulários até que o formulário seja salvo e hook_field_is_empty()possa entrar em ação ( hook_field_is_empty()é configurado de forma que = null ou = array () sinalize vazio).
  • Carregando a entidade entity_load(), desmarcando a entrada do campo por chave e salvando com field_attach_update(). Isso parece não fazer nada - parece que o Drupal interpreta a entrada não estando lá como um sinal para não modificá-la. (estranhamente, às vezes também recebo o tempo limite de expiração do tempo máximo de consulta ao tentar esta abordagem)
  • field_attach_delete() - isso é muito franco: mata todos os campos da entidade
  • field_purge_data() - melhor, mas ainda muito franco: mata todas as entradas do campo, não entradas específicas

Então, para esclarecer, eu tenho um código que encontra (e carrega) uma entidade que possui um campo que possui várias entradas e que encontra uma entrada específica nesse campo que precisa ser removida. Desejo remover completamente essa entrada, sem tocar em nenhuma outra entrada ou em qualquer outro campo da entidade.

user56reinstatemonica8
fonte

Respostas:

24

Se você puder confiar no módulo API da entidade, poderá usar um código semelhante ao seguinte:

// 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
fonte
2
Isso funcionou! Obrigado, meu problema com zumbis foi erradicado. Algumas anotações que podem economizar tempo de outras pessoas: eu precisava atualizar a API da entidade para RC2; desde que eu estava usando um nome de campo dinâmico, a linha não configurada precisava de chaves como não definida ($ entity -> {$ field_name} [LANGUAGE_NONE] [$ index]); e para evitar um aviso, eu precisava envolver o array_values ​​() em if (! empty (...)) {}
user56reinstatemonica8
Isso também funciona se você quiser apenas para limpar o campo inteiro, e evita o temido "Integridade violação de restrição: 1048 Coluna 'field_duty_user_target_id' não pode ser nulo"
Darrell Duane
Muito obrigado! tentou alterar o valor do campo através do node_load, mas não funcionou. Portanto, alterar o valor do campo da entidade como esse definitivamente funciona!
685688
1

Eu precisava fazer isso como parte de uma limpeza de migração do Drupal8.

Após algumas experiências, descobri que a iteração e o uso de unset () no delta poderiam matá-lo. Meu exemplo foi remover uma tag (portanto, procuro por 'target_id', não 'value', como você costuma fazer em outros campos.

/**
 * 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 depois, se o sucesso, então $object->save();

dman
fonte
0

Para o Drupal 8, para excluir um campo de uma entidade:

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

Isso chamará o método mágico __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ão esqueça que, para manter suas alterações, você precisa ligar para

$entity->save();

Depois de fazer todas as suas alterações.

Miguel Guerreiro
fonte
-1

Esta é a melhor maneira:

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

o método preferido atual empregaria o entity_metadata_wrapper

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

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

este é o melhor tutorial sobre a EMW que eu já vi http://deeson-online.co.uk/labs/programatically-access-field-data-using-entitymetadatawrapper-drupal

dotista
fonte
isso não funcionou. Eu até tentei assim sem sorte; $ wrapper = entity_metadata_wrapper ('nó', $ duty); não definido ($ wrapper-> field_duty_user); $ wrapper-> save (); node_save ($ duty);
Darrell Duane
1
A maneira correta seria $ node_wrapped-> field_name-> set (""); Então $ wrapper-> save ()
chadpeppers