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.

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

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


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.


-1

Esta é a melhor maneira:

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

-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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.