Récupérer une valeur de champ sans charger le nœud entier?

11

J'ai un grand nombre de NID et j'ai besoin d'une valeur de champ de chaque nœud. Existe-t-il un moyen d'éviter la surcharge de chargement du nœud entier pour obtenir une valeur de champ?

Joren
la source

Réponses:

19

Je ne pense pas qu'il y ait quelque chose de intégré à l'API, mais en un clin d'œil, vous pouvez simplement interroger la base de données directement:

$entity_type = 'node';
$bundle = 'page';
$nids = array(1, 2, 3);

$field_values = db_select('field_revision_FIELD_NAME', 'f')
  ->fields('f', array('entity_id', 'FIELD_NAME_value'))
  ->condition('entity_type', $entity_type)
  ->condition('bundle', $bundle)
  ->condition('entity_id', $nids, 'IN')
  ->condition('deleted', 0)
  ->execute()
  ->fetchAllKeyed();

Après avoir exécuté cela, vous devriez avoir un tableau de valeurs de champ, saisies par le nid de leur nœud respectif.

Il convient de se rappeler que le nom de la colonne ne le sera pas nécessairement FIELD_NAME_value; par exemple, un champ de référence de nœud aurait un nom de colonne de FIELD_NAME_nid. Lequel vous utiliserez dépendra de votre type de champ.

METTRE À JOUR

Il semble qu'il existe un moyen de le faire avec l'API, mais ce n'est pas joli et implique toujours une requête manuelle:

// Get the field meta data for the field_id.
$field_name = 'field_something';
$field_info = field_info_field($field_name);
$field_id = $field_info['id'];

// Load up the properties from the node table.
$nids = array(1, 2, 3);
$sql = 'SELECT * FROM {node} WHERE nid IN (:nids)';
$nodes = db_query($sql, array(':nids' => $nids))->fetchAllAssoc('nid');

// Attach the single field to all nodes.
field_attach_load('node', $nodes, FIELD_LOAD_CURRENT, array('field_id' => $field_id));

Cette méthode tire parti du $optionsparamètre in field_attach_load()en spécifiant un ID de champ pour lequel charger les données. Il convient de noter, selon la documentation:

Notez que les entités renvoyées peuvent contenir des données pour d'autres champs, par exemple si elles sont lues dans un cache.

Le code peut donc sembler charger des données de champ supplémentaires, mais tout autre que le champ que vous avez spécifié proviendra du cache.

Clive
la source
Impressionnant. Fonctionne parfaitement et BEAUCOUP plus rapidement que le chargement de l'ensemble du nœud.
Joren
J'ai utilisé cette approche avec l'entité utilisateur pour charger la valeur d'un seul champ, mais cette méthode charge tous les champs (et leurs valeurs) associés à l'objet utilisateur. Suis-je en train de manquer quelque chose?
WM
Avertissement: le premier exemple nécessite de stocker les champs dans la base de données SQL (par défaut) et n'est pas compatible avec les autres stockages de champs. Le second devrait fonctionner (car il utilise field_attach_load et il fonctionnera avec l'abstraction des stockages).
Bobík
@Clive, y a-t-il une raison pour laquelle vous avez utilisé field_revision_FIELD_NAME au lieu de field_data_FIELD_NAME? Pouvez-vous s'il vous plaît expliquer? Merci.
Sandesh Yadav
3

Je trouve un moyen un peu plus propre en utilisant un entityCondition et une charge d'attache de champ.

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'story')
  ->propertyCondition('status', 1)
  ->fieldCondition('field_story_image', 'fid', 'NULL', '!=');
$result = $query->execute();

if (isset($result['node'])) {
  $stories = $result['node'];

  // At first we need to get field's id. If you already know field id, you can ommit this step
  // Get all fields attached to a given node type
  $fields = field_info_instances('node', 'story');

  // Get id of body field
  $field_id = $fields['field_story_image']['field_id'];

  // Attach a field of selected id only to get value for it
  field_attach_load('node', $stories, FIELD_LOAD_CURRENT, array('field_id' => $field_id));

  // Get values of our node field
  $output = field_get_items('node', $stories, 'field_story_image');
}

Depuis le blog http://timonweb.com/loading-only-one-field-from-an-entity-or-node

gagarine
la source
0

Pour éviter de charger un nœud un par un avec un grand nombre de NID, vous pouvez utiliser node_load_multiple()ce qui chargera plusieurs nœuds à la fois:

node_load_multiple($nids = array(), $conditions = array(), $reset = FALSE)

Normalement, le chargement des nœuds est mis en cache et c'est rapide si vous utilisez la mémoire cache (comme memcached), mais cela peut être lent si vous avez trop de modules installés (comme Pathauto, etc.).

Une autre façon est de réutiliser l'objet existant, alors vérifiez si vous pouvez le charger directement à partir du cache (par exemple via form_get_caches'il fait partie du formulaire) ou à partir de la $_POSTdemande.

Une autre façon consiste à utiliser EntityFieldQueryavec plusieurs NID, par exemple

$query->entityCondition('entity_id', array(17, 21, 422), 'IN')

qui va récupérer les valeurs directement à partir de la base de données.

Kenorb
la source