以编程方式从一个实体的一个字段中删除一个条目


13

以编程方式从一个特定实体中删除多条目字段的一个特定字段条目的正确方法是什么?(这是特定的字段和特定的实体,不是字段类型或实例和实体类型)

这是我研究过的一些不起作用的可能性:

  • 使用加载实体entity_load(),将字段条目设置为= null或= array(),然后使用保存field_attach_update()。这是我找到的最接近的,但它在数据库中留下了一个僵尸null字段条目,该条目在表单上显示为空白行,直到保存表单并hook_field_is_empty()可以将其踢入为止(hook_field_is_empty()配置为= null或= array()将进行标记为空)。
  • 用加载实体entity_load(),通过键取消设置字段条目,然后用保存field_attach_update()。这似乎无济于事-似乎Drupal将该条目解释为不修改该条目的标志。(奇怪的是,有时我在尝试这种方法时有时也会得到最大查询时间过期超时)
  • field_attach_delete() -这太直率了:它会杀死实体的所有字段
  • field_purge_data() -更好,但仍然太钝:它会杀死该字段的所有条目,而不是特定条目

因此,为澄清起见,我有代码来查找(并加载)一个实体,该实体的字段具有多个条目,并在该字段上找到需要删除的特定条目。我想完全删除该条目,而无需触摸实体上的任何其他条目或任何其他字段。

Answers:


24

如果您能够依赖实体API模块,则应该能够使用类似于以下内容的代码:

// 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
这工作了!谢谢,我的僵尸问题现在已经根除。一些注意事项可能会节省其他时间:我需要将实体api更新为RC2;由于我使用的是动态字段名称,因此未设置的行需要使用大括号,例如unset($ entity-> {$ field_name} [LANGUAGE_NONE] [$ index]);为了避免警告,我需要将array_values()包装在if(!empty(...)){}中
user56reinstatemonica8

如果您只想清除整个字段,也可以避免可怕的“违反完整性约束:1048列'field_duty_user_target_id'不能为空”
Darrell Duane

非常感谢!试图通过node_load更改字段值,但是没有用。因此,像这样更改实体字段值绝对有效!
АртемИльин

1

在Drupal8迁移清理中,我需要执行此操作。

经过一些实验,我发现迭代然后在delta上使用unset()可能会杀死它。我的示例删除了一个标记(因此,我搜索“ target_id”,而不是像其他字段那样经常搜索“ value”)。

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

然后,如果成功,那么 $object->save();


0

对于Drupal 8,要从实体中删除字段:

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

这将从ContentEntityBase调用魔术方法__unset():

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

不要忘记,要保持更改,您需要致电

$entity->save();

完成所有更改后。


-1

这是更好的方法:

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

-2

当前的首选方法将采用entity_metadata_wrapper

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

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

这是我见过的有关EMW的最佳教程,网址为http://deeson-online.co.uk/labs/programatically-access-field-data-using-entitymetadatawrapper-drupal


这没有用。我什至没有运气就这样尝试过;$ wrapper = entity_metadata_wrapper('node',$ duty); 取消设置($ wrapper-> field_duty_user); $ wrapper-> save(); node_save($ duty);
Darrell Duane 2014年

1
正确的方法是$ node_wrapped-> field_name-> set(“”); 然后$ wrapper-> save()
chadpeppers 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.