Cree una EntityFieldQuery que seleccione entidades referenciadas

10

Estoy buscando el ID de la entidad de tipo A y sé el ID de la entidad B que hace referencia a A.

Encontré algunas buenas fuentes sobre EntityFieldQuery. Me sorprendió que obtuviera resultados de .NET en google :) (¿es un signo de la madurez de Drupal? :). Pero no logró encontrar esto. Por favor ayuda ...

Algunas de las fuentes:

Esto es lo que parece con las cargas de entidades: comprenderá que necesito esa consulta :) El contenedor está allí para practicar principalmente. Tenga en cuenta que carga la entidad objetivo, muchas consultas.

  $b = entity_load('B', array($id));
  $bm = entity_metadata_wrapper('B', $sl[$id]);

  $tsl = $slm->field_sl_tpref->value();
  echo $tsl->id;
mojzis
fuente
1
Un EntityFieldQuerysolo puede hacer referencia a un conjunto de entidades, desafortunadamente no puede crear relaciones con otras entidades. También solo puede devolver un tipo de entidad a la vez, por lo que incluso si pudiera crear estas relaciones, los resultados no serían confiables.
Clive
@Clive, ¿le importaría agregar eso como respuesta, para que pueda confirmarlo? gracias :)
mojzis

Respuestas:

15

Puede usar en target_idlugar de valuerecuperar entidades basadas en la ID de las entidades referenciadas:

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', <type-of-the-entity>);
$query->fieldCondition('<name-of-the-field-referring-the-other-entity>', 'target_id', <id-of-the-referenced-entity>, '=');
$results = $query->execute();
pablo
fuente
gracias, pero no creo que eso sea lo que estaba buscando ... estaba tratando de tomar la otra dirección, así conocerías la A y buscarías la B :)
mojzis
2

err, ¿es el módulo de relación lo que está buscando? Parece que definir relaciones entre entidades X e Y es lo que quieres hacer. tiene su propio RelationQuery (un contenedor alrededor de EFQ) y RelationQueryEndpoints para obtener fácilmente este tipo de información.

Tenken
fuente
Gracias. desafortunadamente, ya he definido algunas relaciones con la referencia de entidad, por lo que cambiar a una relación sería problemático ... lo intentaré la próxima vez :).
mojzis
2

Sé que esta es una pregunta anterior, pero para las personas que llegan a esto desde Google, pensé que lanzaría otro enfoque aquí.

De la descripción anterior, la configuración tiene 2 tipos de entidad, A y B. B hace referencia a A con la referencia de entidad que supongo. Entonces, si tiene la identificación de B, debe tener un campo con la identificación de A almacenada en la base de datos.

Notas de código:

  • NID original: $original_node->nidesta sería la ID de B
  • Tipo de paquete: $typeeste debería ser el tipo de A
  • La condición de campo solo busca el campo que contiene la referencia
  • Para obtener más información sobre cómo usar EFQ, vea esto

Código

// Start a new EFQ
$query = new EntityFieldQuery();

// Define query, the user load is probably not needed but sometimes is.
$query->entityCondition('entity_type', 'node')
      ->entityCondition('bundle', $type)
      ->fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=')
      ->addMetaData('account', user_load(1));

// Execute query, result with have node key
$result = $query->execute();

// If results it will be in node key
if (isset($result['node'])) {
  $nids = array_keys($result['node']);
  // This example has multiple nodes being referenced by one node
  $nodes = node_load_multiple($nids, array('type' => $type));
  // Devel module needed
  dpm($nodes);
}

También puede configurar referencias de entidades bidireccionales y hacer la misma consulta al revés. Puede usar un módulo como CER para asegurarse de que esas referencias se mantengan actualizadas. O configure una regla para mantener actualizada la referencia, he usado ambos.

Burnsjeremy
fuente
Si field_NAME_OF_FIELD es multivalor, ¿ fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=')funcionará? debe ser cambiado a fieldCondition('field_NAME_OF_FIELD', 'target_id', array($original_node->nid), 'IN'). No se pudo encontrar nada sobre cómo aplicar la condición en el campo de referencia de entidad multivalor. ¿cualquier sugerencia?
kiranking
1
Sé que este es un comentario antiguo, pero si dejas el '=' desactivado, EntityFieldQuery tiene el valor predeterminado IN, por lo que fieldCondition ('field_NAME_OF_FIELD', 'target_id', $ original_node-> nid) realmente funcionaría en esa situación. Probablemente ya lo sepas, pero solo en caso de que alguien más se encuentre con eso más tarde :)
burnsjeremy
1

una solución bastante dinámica (un poco sucia también, pero la necesitaba rápidamente), por lo que no necesita codificar el nombre del campo de referencia y se maneja automáticamente con un nuevo campo de referencia que agregará en el futuro:

en su módulo personalizado:

/**
 * Implement hook_field_create_instance().
 */
function MY_CUSTOM_MODULE_field_create_instance() {
  _MY_CUSTOM_MODULE_set_variable_node_back_references();
}

/**
 * Implement hook_field_delete_field().
 */
function MY_CUSTOM_MODULE_field_delete_field() {
  _MY_CUSTOM_MODULE_set_variable_node_back_references();
}

/**
 * Set Variable node_back_references.
 */
function _MY_CUSTOM_MODULE_set_variable_node_back_references() {
  $field_list = db_select('field_config', 'fc')
    ->fields('fc', array('field_name', 'data'))
    ->condition('fc.data', '%"foreign keys";a:1:{s:4:"node"%', 'like')
    ->condition('fc.deleted', 0);
  $field_list->innerJoin('field_config_instance', 'fci', 'fci.field_name = fc.field_name');
  $field_list->rightJoin('node_type', 'n', 'n.type = fci.bundle');
  $fields = $field_list->execute()->fetchAll();

  $fields_array = array();
  foreach ($fields as $field) {
    $unserialized = unserialize($field->data);
    if (isset($unserialized['settings']['handler_settings']['target_bundles'])) {
      foreach ($unserialized['settings']['handler_settings']['target_bundles'] as $bundle) {
        $fields_array[$bundle][] = $field->field_name;
      }
    }
  }

  variable_set('node_back_references', $fields_array);
}

function _MY_CUSTOM_MODULE_get_referencing_nodes($node) {
  $nids = array();
  $fields = variable_get('node_back_references', array());
  if (isset($fields[$node->type])) {
    foreach ($fields[$node->type] as $field) {
      $query = new \EntityFieldQuery();
      $query->entityCondition('entity_type', 'node');
      $query->propertyCondition('status', 1);
      $query->fieldCondition($field, 'target_id', $node->nid);
      $result = $query->execute();
      $nids = isset($result['node']) ? array_merge(array_keys($result['node']), $nids) : $nids;
    }
    $nodes = (!empty($nids)) ? node_load_multiple($nids) : array();

    return $nodes;
  }

  return $nids;
}

donde necesita obtener los nodos primarios dado el nodo secundario:

$nodes = _MY_CUSTOM_MODULE_get_referencing_nodes($node);
Gueno
fuente