Elimine programáticamente una entrada de un campo en una entidad

13

¿Cuál es la forma correcta de eliminar mediante programación una entrada de campo específica para un campo de múltiples entradas de una entidad específica? (son campos específicos y entidades específicas, no tipos de campos o instancias y tipos de entidades)

Aquí hay algunas posibilidades que he analizado que no funcionan:

  • Cargando la entidad con entity_load(), estableciendo la entrada de campo en = nulo o = matriz (), luego guardando con field_attach_update(). Es lo más cercano que he encontrado, pero deja una entrada de campo nulo zombie en la base de datos que se muestra como una fila en blanco en los formularios hasta que el formulario se guarda y hook_field_is_empty()puede iniciarse ( hook_field_is_empty()está configurado de manera que = nulo o = matriz () marcará como vacio)
  • Cargando la entidad con entity_load(), desarmando la entrada de campo por clave, luego guardando confield_attach_update() . Esto parece no hacer nada, parece que Drupal interpreta que la entrada no está allí como una señal para no modificarla. (curiosamente, a veces también obtengo tiempos de espera de tiempo de consulta máximos al intentar este enfoque)
  • field_attach_delete() - esto es demasiado contundente: mata todos los campos de la entidad
  • field_purge_data() - mejor, pero aún demasiado contundente: elimina todas las entradas del campo, no entradas específicas

Entonces, para aclarar, tengo un código que encuentra (y carga) una entidad que tiene un campo que tiene múltiples entradas, y encuentra una entrada específica en ese campo que debe eliminarse. Quiero eliminar esa entrada por completo, sin tocar ninguna otra entrada o cualquier otro campo en la entidad.

user56reinstatemonica8
fuente

Respuestas:

24

Si puede confiar en el módulo API de la entidad , debería poder usar un código similar al siguiente:

// 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
fuente
2
Esto funcionó! Gracias, mi problema zombie ahora ha sido erradicado. Algunas notas que podrían ahorrarle tiempo a otros: necesitaba actualizar la API de la entidad a RC2; como estaba usando un nombre de campo dinámico, la línea sin definir necesitaba llaves como unset ($ entity -> {$ field_name} [LANGUAGE_NONE] [$ index]); y para evitar una advertencia, necesitaba ajustar el array_values ​​() en if (! empty (...)) {}
user56reinstatemonica8
Esto también funciona si solo desea borrar todo el campo y evita la temida "violación de restricción de integridad: 1048 La columna 'field_duty_user_target_id' no puede ser nula"
Darrell Duane
¡Muchas gracias! intentó cambiar el valor del campo a través de node_load, pero no funcionó. ¡Cambiar el valor del campo de entidad como este definitivamente funciona!
Артем Ильин
1

Necesitaba hacer esto como parte de una limpieza de migración de Drupal8.

Después de experimentar un poco, descubrí que iterar y luego usar unset () en el delta podría matarlo. Mi ejemplo fue eliminar una etiqueta (por lo tanto, busco 'target_id', no 'value' como lo haría a menudo para otros 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;
}

Y luego, si el éxito, entonces $object->save();

dman
fuente
0

Para Drupal 8, para eliminar un campo de una entidad:

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

Esto llamará al 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]);
    }
}

No olvide que, para persistir en sus cambios, debe llamar

$entity->save();

Después de que hayas hecho todos tus cambios.

Miguel Guerreiro
fuente
-1

Esta es la mejor manera:

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

el método preferido actual emplearía la entidad_metadata_wrapper

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

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

este es el mejor tutorial sobre EMW que he visto http://deeson-online.co.uk/labs/programatic-access-field-data-using-entitymetadatawrapper-drupal

dotist
fuente
Esto no funcionó. Incluso lo intenté así sin suerte; $ wrapper = entity_metadata_wrapper ('nodo', $ duty); unset ($ wrapper-> field_duty_user); $ wrapper-> save (); node_save ($ duty);
Darrell Duane
1
La forma correcta sería $ node_wrapped-> field_name-> set (""); luego $ wrapper-> save ()
chadpeppers