如何使用entity_metadata_wrapper()清除字段值?


20

假设我有一个带有字段的实体,field_foo并且想清除该字段的值。

我应该传递给$wrapper->set()什么?

我已经尝试过NULLarray()并且都产生错误消息。



::clear直接调用并不等同于将该字段设置为空值,因为它不会像调用空值那样进行updateParent调用set。除其他外,updateParent确保调用setter callback属性信息中的定义(请参阅drupalcontrib.org/api/drupal/…)。
爱丽丝·希顿

Answers:


24

问题是您必须设置一个与字段的数据类型兼容的空值。如果不这样做,则会引发异常。因此,如果传递NULL或传递array()期望的字符串,则会引发错误。

要记住的另一件事是,您传递的数据还将取决于您的字段是单个值,多值字段还是具有多个属性的字段。

如果您的字段是单个值(因此该字段的包装器是EntityValueWrapper的实例),则应为它分配一个与所讨论的数据类型兼容的空值。例如,以下两种方法是等效的:

$wrapper->title = '';
$wrapper->title->set('');

但是,以下三个示例将引发异常,因为数据类型与title字段不兼容:

$wrapper->title->set();
$wrapper->title->set(NULL);
$wrapper->title->set(array());

如果您的字段是具有多个属性的字段(例如,同时定义a valueformat属性的格式化文本字段),因此是EntityStructureWrapper的实例,则array()NULL将是正确的空值。因此,您可以执行以下操作:

$wrapper->field_formatted_text = array();
$wrapper->field_formatted_text = NULL;

但是在那种情况下,传递空字符串会引发错误。请注意,您可以选择将value属性设置为空,在这种情况下,字符串是正确的数据类型:

$wrapper->field_formatted_text->value = '';

最后,如果您的字段是一个多值字段(因此您的包装器是EntityListWrapper的实例),则array或是NULL正确的空值,并且以下三行等效:

$wrapper->field_example_multiple->set();
$wrapper->field_example_multiple = array();
$wrapper->field_example_multiple = NULL;

注意:clear在包装器上调用方法并不等同于将字段设置为空值。当字段设置为空值时,它将在字段的父包装器上调用EntityMetadataWrapper :: updateParent。除其他外,这确保了setter callbackhook_entity_property_info定义的调用。调用clear不这样做。


1
请注意,如果该字段是多个字段并且是必填字段,则设置为array()NULL可能会失败,因为该字段不能为空。这与常规$node字段分配不同,在常规字段分配中,您可以通过编程方式保存一个空的必填字段(它不会通过Drupal自己的UI保存)。在这种情况下,解决方法是array(N),其中N是不存在但尚未引用的实体的ID。请注意,它将使用该ID进行保存,因此从关系上讲,您的数据可以说是“损坏的”。但是,如果您在其中进行了所有正确的操作(例如,使用Display Suite或Panel),则不会影响主题层。
JP

$w->field_allowed_regions->set(array(null));是适用于我的多值分类法参考字段的唯一选项。
令人难以置信的

就我而言,我有一个具有单个值的实体引用字段。以下对我有用:$ wrapper-> field_entity_reference-> set(NULL);
Marcos Buarque '18

3

除其他答案和评论外,如果该字段是多个字段且为必填字段,则如前所述,您不能使用

$wrapper->field_example_multiple->set()

$wrapper->field_example_multiple->set(NULL)

甚至也不是$wrapper->field_example_multiple->set(array())

但是,如果要清除其所有值的字段,可以使用以下命令:

$wrapper->field_example_multiple->set(array(NULL));

实际上,无论多值字段是否设置为“ required”,此方法均有效,因此,我建议始终使用此值,以确保您的代码健壮。

(当然,如果该字段是“必填”字段,则无论如何您都不应该完全清除它,但是您的代码可能会将其作为删除整个实体或类似内容的初步步骤,因此有时可能就是合法的。)


请注意,使用`$ wrapper-> field_example_multiple-> set(array(NULL))`将导致数据数组中包含NULL元素。此方法不会清除值,而是将values数组设置为单个NULL值。
Alex Skrypnyk '16

好点子。我想这使我们回到不清除所需值的观点。可能故意使它成为不可能。
马丁Q

实际上,必填字段必须至少具有一个非空值。如果要重置必需的多值字段,只需用新值覆盖它即可。即:$product_display->field_product = array($product_id);
Interdruper

2

看来其他注释中列出的复杂性仅与必填字段有关。如果不需要该字段,那么这应该很简单:

$wrapper->field_foo = NULL;

您可以使用包装器检查字段的属性:

$properties = $wrapper->getPropertyInfo();
$field_required = !empty($properties['field_foo']['required']);

根据上下文,您还可以使用以下方法获取一个字段的属性:

$wrapper->getPropertyInfo('field_foo');

1

解决此问题的另一种方法可能是 EntityMetadataWrapper::clear

$entity_wrapper->field->clear()


EntityMetadataWrapper :: clear方法被声明为“受保护”,因此无法从您的代码中调用:只能从对象外部直接访问“公共”方法。
Interdruper
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.