Como você limpa um valor de campo com entity_metadata_wrapper ()?

20

Suponha que eu tenha uma entidade com um campo field_fooe queira limpar o valor desse campo.

O que devo passar $wrapper->set()?

Eu tentei NULLe array()ambos produzem uma mensagem de erro.

joachim
fonte
11
Você está procurando os métodos EntityStructureWrapper::clear()ou EntityValueWrapper::clear()talvez?
Clive
Chamar ::cleardiretamente não é equivalente a definir o campo para um valor vazio, pois não chama updateParentda mesma forma que chama setcom um valor vazio. Entre outras coisas, updateParentgarante que o setter callbackdefinido nas informações da propriedade (consulte drupalcontrib.org/api/drupal/… ) seja chamado.
Alice Heaton

Respostas:

24

O problema é que você deve definir um valor vazio que seja compatível com o tipo de dados do seu campo. Caso contrário, você receberá uma exceção. Passar NULLou array()quando uma sequência é esperada gerará um erro.

Outro aspecto a ter em mente é que os dados transmitidos também dependerão se o seu campo for um valor único, um campo com vários valores ou um campo com várias propriedades.

Se o seu campo for um valor único (e, portanto, o wrapper do campo for uma instância do EntityValueWrapper ), você deverá atribuir a ele um valor vazio compatível com o tipo de dados em questão . Por exemplo, os dois métodos a seguir são equivalentes:

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

No entanto, os três exemplos a seguir gerarão uma exceção, porque os tipos de dados não são compatíveis com o titlecampo:

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

Se o seu campo for um campo com várias propriedades (por exemplo, um campo de texto formatado, que definiu a valuee a formatpropriedade) e, portanto, uma instância do EntityStructureWrapper , array()ou NULLserá o valor vazio correto. Então você pode fazer o seguinte:

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

Mas, nesse caso, passar uma string vazia teria gerado um erro. Observe que você poderia optar por deixar a valuepropriedade vazia . Nesse caso, uma sequência é o tipo de dados correto:

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

Finalmente, se o campo é um campo multi-valor (e, assim, o seu invólucro é um exemplo de EntityListWrapper ), em seguida, arrayou NULLsão os valores de correcção vazios, e as três linhas seguintes são equivalentes:

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

Nota: Chamar o clearmétodo nos wrappers não é equivalente a configurar o campo para um valor vazio. Quando o campo é definido como um valor vazio, ele chama EntityMetadataWrapper :: updateParent no wrapper pai do campo. Isso garante, entre outras coisas, que o setter callbackdefinido por hook_entity_property_info seja chamado. Ligar clearnão faz isso.

Alice Heaton
fonte
11
Observe que, se o campo for múltiplo e obrigatório, configure como array()ou NULLpode falhar, porque o campo não pode estar vazio. Isso é diferente da $nodeatribuição de campo normal , onde é possível salvar programaticamente um campo obrigatório vazio (ele não será salvo pela interface do Drupal). Nesse caso, uma solução alternativa é array(N), onde N é o ID de uma entidade ainda não existente e referenciada. Observe que ele será salvo com esse ID; portanto, seus dados são "quebrados" em um sentido relacional; mas não deve afetar a camada do tema se você estiver fazendo as coisas certas (por exemplo, usando o Display Suite ou os painéis).
JP
$w->field_allowed_regions->set(array(null));é a única opção que funcionou para o meu campo de referência de taxonomia com vários valores.
Incredible
No meu caso, tenho um campo de referência de entidade com um único valor. O seguinte funcionou para mim: $ wrapper-> field_entity_reference-> set (NULL);
Marcos Buarque
3

Além de outras respostas e comentários, se o campo for múltiplo e obrigatório, conforme observado anteriormente, você não poderá usar

$wrapper->field_example_multiple->set()

$wrapper->field_example_multiple->set(NULL)

nem mesmo $wrapper->field_example_multiple->set(array()),

mas, em vez disso, você pode usar o seguinte se quiser limpar o campo de todos os seus valores:

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

De fato, isso funciona se o campo de valores múltiplos está ou não definido como 'obrigatório' e, portanto, recomendo sempre usá-lo, para garantir que seu código seja robusto.

(Obviamente, se o campo for 'obrigatório', você talvez não deva limpá-lo completamente, mas seu código pode estar fazendo isso como uma etapa preliminar para excluir a entidade inteira ou algo semelhante, portanto, há momentos em que pode apenas seja legítimo.)

Martin Q
fonte
Esteja ciente de que o uso de $ $ wrapper-> field_example_multiple-> set (array (NULL)) `levará a ter um elemento NULL no array de dados. Este método não limpa valores, mas define a matriz de valores para um único NULLvalor.
precisa
Bom ponto. Eu acho que isso nos remete à minha observação sobre não limpar um valor necessário. Provavelmente é impossível de forma intencional.
Martin Q
De fato, um campo obrigatório deve ter pelo menos um valor não nulo. Se você deseja redefinir um campo de vários valores obrigatório, basta substituí-lo pelo novo valor. $product_display->field_product = array($product_id);
Ou
2

Parece que as complexidades listadas nos outros comentários são relevantes apenas para um campo obrigatório. Se o campo não for obrigatório, isso deve ser bastante simples:

$wrapper->field_foo = NULL;

Você pode usar o wrapper para verificar as propriedades do campo:

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

Dependendo do contexto, você também pode obter as propriedades de um campo usando:

$wrapper->getPropertyInfo('field_foo');
Giles B
fonte
1

Outra solução para esse problema pode ser EntityMetadataWrapper::clear

$entity_wrapper->field->clear()

Mouneer
fonte
O método EntityMetadataWrapper :: clear é declarado como "protegido", portanto, não pode ser chamado a partir do seu código: somente métodos "públicos" podem ser acessados ​​diretamente de fora do objeto.
Interdruper 27/03/16