Accès aux valeurs de types de champs inconnus lors de l'utilisation de entity_metadata_wrapper

12

J'ai cherché à utiliser les classes Entity Metadata Wrapper (définies par le module d'entité dans Drupal 7) pour accéder aux valeurs de champ, car cela semble être une manière propre de le faire.

Il y a quelques choses qui rendent cela un peu gênant cependant. Supposons que j'ai un wrapper pour un type de contenu qui définit un champ nommé field_somethingcomme tel:

$wrapper = entity_metadata_wrapper('node', node_load($nid));
$value = $wrapper->field_something->value();

Le premier problème que j'ai est que je n'ai aucun moyen de savoir à l'avance si ce que j'obtiens est une valeur réelle (une chaîne, une entité, etc.), un autre wrapper de structure de métadonnées (lorsque les champs ont plusieurs valeurs) ou un tableau (lorsque les champs ont plusieurs propriétés).

J'ai trouvé un moyen de répondre à ces questions en utilisant la info()méthode:

$info = $wrapper->field_something->info();
$is_multi_value = (strpos($info['type'], 'list<') === 0);
$has_multiple_properties = isset($info['property info']]);

Mais ce n'est guère pratique. Chaque fois que je veux utiliser un champ sans connaître sa définition au préalable, je dois prendre en compte plusieurs cas. Cela rend mon code assez lourd.

Pour y faire face, j'ai écrit du code qui:

  1. Garantit que nous recevons toujours un tableau, même s'il s'agit d'un champ à valeur unique;
  2. Lorsqu'il existe plusieurs propriétés, renvoyez la valeur de la première colonne.

Le point 1 ici fonctionnera toujours, à moins que l'appelant ne veuille savoir s'il s'agit d'un champ à valeur unique ou non. Le point 2 fonctionne dans certains cas, pas tous, mais est pratique lorsqu'il s'applique.

Voici le code:

function entity_metadata_simple_values($field) {
  $fields = array();
  $values = array();
  $info = $field->info();
  if (strpos($info['type'], 'list<') === 0) {
    foreach ($field->getIterator() as $field_iteration) {
      $fields[] = $field_iteration;
    }
  } else {
    $fields[] = $field;
  }
  foreach ($fields as $final_field) {
    $ff_info = $final_field->info();
    if (isset($ff_info['property info'])) {
      $column = reset(array_keys($ff_info['property info']));
      $values[] = $final_field->{$column}->value();
    } else {
      $values[] = $final_field->value();
    }
  }

  return $values;
}

Ma question est donc la suivante: existe-t-il des moyens plus simples / meilleurs de résoudre ce problème d'obtention de valeurs à partir du wrapper de métadonnées lorsque le type de champ n'est pas connu?

Alice Heaton
la source

Réponses:

4

Voici quelques suggestions pour rendre ce processus un peu plus facile.

$wrapper->field_something->type();

retourne le type du champ, à savoir node, taxonomy_term, integer, textetc. Vous pouvez ensuite gérer la valeur retournée par $wrapper->field_something->value()correctement.

Aussi

$wrapper->field_something->raw()

renverra la valeur brute du champ. Ce qui sera soit un arraydans le cas de champs multi-valeurs de juste la valeur. Par exemple, un entity_referencesera le nid(ou l'identifiant d'entité) de l'entité référencée, ou un arraydes identifiants d'entité référencés.

thepearson
la source
Oups, je suis entré trop vite! Je voulais ajouter: $ wrapper-> field_something-> type () renvoie les mêmes informations que l'élément 'type' du tableau retourné par $ wrapper-> field_something-> info (). Fondamentalement, il renvoie toujours une chaîne "list <type>" pour les types à valeurs multiples, j'ai donc toujours besoin d'un strpos (ou équivalent) pour déterminer qu'il est à plusieurs valeurs (si je veux le travailler avant de le récupérer).
Alice Heaton
Quant au deuxième point: je peux en effet déterminer si elle est multi-valeurs en testant le retour de -> raw () ou de -> value (), mais je préfère savoir avant d'aller chercher la valeur, comme si elle était multi-valeurs alors Je veux l'exécuter à travers une boucle foreach avec -> getIterator () plutôt que de parcourir manuellement le tableau, ce qui m'oblige à recréer un wrapper pour chaque élément.
Alice Heaton
3

Donc, comme personne n'a trouvé une autre solution, je répondrai à ma propre question:

Il n'y a pas de moyen plus simple d'accéder aux valeurs de types de champs inconnus lors de l'utilisation d'encapsuleurs de métadonnées d'entité.

Il existe des méthodes alternatives à celle que j'ai décrite initialement (par exemple celles indiquées par @thepearson). En particulier, cette méthode est utile:

 entity_property_list_extract_type($type)

Il renverra le type répertorié si votre type est une liste (par exemple, «entier» si votre type est «liste <entier>»), ou faux si votre type n'est pas une liste. En interne, il fait une strpos, tout comme le code que j'ai initialement publié, mais je suppose que c'est plus à l'épreuve du temps.

La conclusion est que:

  • Les wrappers de métadonnées d'entité fonctionnent bien si vous n'avez aucune idée de vos types de champs et que vous souhaitez traiter soigneusement chaque cas possible;

  • Les wrappers de métadonnées d'entité fonctionnent bien si vous savez exactement de quels types sont vos champs et que vous souhaitez les utiliser;

  • Si vous n'avez que quelques idées sur la nature de vos types de champs (par exemple, tout le texte, mais vous ne savez pas s'ils sont formatés ou non, et vous ne savez pas s'ils sont à valeur unique ou multiple), alors les wrappers de métadonnées d'entité ne fournissez aucun raccourci et vous devez écrire le vôtre comme je l'ai fait dans la question initiale.

Alice Heaton
la source
1

Pour la vérification de champ unique / multiple, j'ai trouvé utile de tester le type de l'objet wrapper, qui sera EntityListWrapperpour un champ à valeurs multiples et EntityValueWrapperpour un champ à valeur unique:

<?php
...
$wrapper = entity_metadata_wrapper('user', $account);
// Get address, or first address if a multi-value field instance.
if (get_class($wrapper->field_address) == 'EntityListWrapper') {
  $value = $wrapper->field_address[0]->value();
}
else {
  $value = $wrapper->field_address->value();
}
Fonant
la source
Ou mêmeif($wrapper->field_name instanceof EntityListWrapper) {...}
rudolfbyker