Comment effacer une valeur de champ avec entity_metadata_wrapper ()?

20

Supposons que j'ai une entité avec un champ field_foodessus et que je veuille effacer la valeur de ce champ.

À quoi dois-je passer $wrapper->set()?

J'ai essayé NULLet array()et les deux produisent un message d'erreur.

joachim
la source
1
Cherchez-vous peut-être les méthodes EntityStructureWrapper::clear()ou EntityValueWrapper::clear()?
Clive
Appeler ::cleardirectement n'est pas équivalent à définir le champ sur une valeur vide, car il n'appelle pas updateParentde la même manière que l'appel setavec une valeur vide. Entre autres choses, updateParentgarantit que l' appel setter callbackdéfini dans les informations de propriété (voir drupalcontrib.org/api/drupal/… ).
Alice Heaton

Réponses:

24

Le problème est que vous devez définir une valeur vide compatible avec le type de données de votre champ. Si vous ne le faites pas, vous obtiendrez une exception levée. Passer NULLou array()quand une chaîne est attendue provoquera donc une erreur.

Une autre chose à garder à l'esprit est que les données que vous transmettez dépendent également du fait que votre champ est une valeur unique, un champ à plusieurs valeurs ou un champ avec plusieurs propriétés.

Si votre champ est une valeur unique (et donc le wrapper pour le champ est une instance de EntityValueWrapper ), vous devez lui affecter une valeur vide compatible avec le type de données en question . Par exemple, les deux méthodes suivantes sont équivalentes:

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

Cependant, les trois exemples suivants lèveront une exception, car les types de données ne sont pas compatibles avec le titlechamp:

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

Si votre champ est un champ avec des propriétés multiples (par exemple un champ de texte mis en forme, qui définit à la fois une valueet formatpropriété) et donc une instance de EntityStructureWrapper , alors array()ou NULLsera la valeur vide correcte. Vous pouvez donc effectuer les opérations suivantes:

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

Mais dans ce cas, le passage d'une chaîne vide aurait déclenché une erreur. Notez que vous auriez pu choisir de rendre la valuepropriété vide à la place, auquel cas une chaîne est le type de données correct:

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

Enfin, si votre champ est un champ à plusieurs valeurs (et donc votre wrapper est une instance de EntityListWrapper ), alors arrayou NULLsont les valeurs vides correctes, et les trois lignes suivantes sont équivalentes:

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

Remarque: L'appel de la clearméthode sur les wrappers n'est pas équivalent à définir le champ sur une valeur vide. Lorsque le champ est défini sur une valeur vide, il appelle ensuite EntityMetadataWrapper :: updateParent sur le wrapper parent du champ. Cela garantit entre autres que le setter callbackdéfini par hook_entity_property_info est appelé. Appeler clearne fait pas ça.

Alice Heaton
la source
1
Notez que si le champ est multiple et obligatoire, la définition de array()ou NULLpeut échouer, car le champ ne peut pas être vide. Ceci est différent de l' $nodeaffectation de champ normale , où vous pouvez enregistrer par programme un champ obligatoire vide (il ne sera tout simplement pas enregistré via la propre interface utilisateur de Drupal). Dans ce cas, une solution de contournement est array(N), où N est l'ID d'une entité inexistante mais référencée. Notez qu'il enregistrera avec cet ID, donc vos données sont sans doute "cassées" dans un sens relationnel; mais cela ne devrait pas affecter la couche de thème si vous faites toutes les bonnes choses là-bas (par exemple en utilisant Display Suite ou des panneaux).
JP
$w->field_allowed_regions->set(array(null));est la seule option qui a fonctionné pour mon champ de référence de taxonomie à valeurs multiples.
Incroyable
Dans mon cas, j'ai un champ de référence d'entité avec une seule valeur. Les éléments suivants ont fonctionné pour moi: $ wrapper-> field_entity_reference-> set (NULL);
Marcos Buarque
3

Suite à d'autres réponses et commentaires, si le champ est multiple et obligatoire, comme indiqué précédemment, vous ne pouvez pas utiliser

$wrapper->field_example_multiple->set()

$wrapper->field_example_multiple->set(NULL)

ni même $wrapper->field_example_multiple->set(array()),

mais à la place, vous pouvez utiliser ce qui suit si vous souhaitez effacer le champ de toutes ses valeurs:

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

En fait, cela fonctionne que le champ à valeurs multiples soit défini sur "requis" ou non, et je vous recommande donc de toujours l'utiliser pour vous assurer que votre code est robuste.

(Bien sûr, si le champ est `` obligatoire '', vous ne devriez peut-être pas le supprimer complètement de toute façon, mais votre code peut le faire comme une étape préliminaire à la suppression de l'entité entière ou quelque chose de similaire, donc il peut y avoir des moments où il peut soyez juste légitime.)

Martin Q
la source
Sachez que l'utilisation de `$ wrapper-> field_example_multiple-> set (array (NULL))` entraînera la présence d'un élément NULL dans le tableau de données. Cette méthode n'efface pas les valeurs mais définit plutôt le tableau de valeurs sur une seule NULLvaleur.
Alex Skrypnyk
Bon point. Je suppose que cela nous ramène à ma remarque sur le fait de ne pas effacer une valeur requise. Cela est probablement rendu impossible intentionnellement.
Martin Q
En fait, un champ obligatoire doit avoir au moins une valeur non nulle. Si vous souhaitez réinitialiser un champ à valeurs multiples requis, remplacez-le simplement par la nouvelle valeur. C'est à dire:$product_display->field_product = array($product_id);
Interdruper
2

Il semble que les complexités énumérées dans les autres commentaires ne concernent qu'un champ obligatoire. Si le champ n'est pas obligatoire, cela devrait être assez simple:

$wrapper->field_foo = NULL;

Vous pouvez utiliser l'encapsuleur pour vérifier les propriétés du champ:

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

Selon le contexte, vous pouvez également obtenir simplement les propriétés d'un seul champ en utilisant:

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

Une autre solution à ce problème pourrait être EntityMetadataWrapper::clear

$entity_wrapper->field->clear()

Mouneer
la source
La méthode EntityMetadataWrapper :: clear est déclarée "protégée", elle ne peut donc pas être appelée à partir de votre code: seules les méthodes "publiques" sont accessibles directement depuis l'extérieur de l'objet.
Interdruper