建立一个EntityFieldQuery选择引用的实体


10

我正在寻找类型A的实体的ID,我知道引用A的实体B的ID。

我找到了一些关于EntityFieldQuery的不错的资源。我很惊讶我在Google .NET中从.NET获得结果(这是Drupal成熟的标志吗?:)。但是没有设法找到这个。请帮忙 ...

一些来源:

这就是实体负载的样子-您将了解我需要该查询:)包装器主要用于练习。请注意,它会加载目标实体-很多查询。

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

  $tsl = $slm->field_sl_tpref->value();
  echo $tsl->id;

1
一个EntityFieldQuery只能引用实体的一组,它不能创造遗憾的是其他实体的关系。它一次只能返回一种类型的实体,因此即使您可以创建这些关系,结果也将不可靠。
克莱夫(Clive)

@Clive您介意将此添加为答案,以便我可以确认吗?谢谢:)
mojzis

Answers:


15

您可以使用target_id而不是value根据所引用实体的ID来检索实体:

$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();

谢谢,但是我认为那不是我想要的...我正试图找到另一个方向,这样您就可以知道A并寻找B :)
mojzis

2

呃,您正在寻找关系模块吗?听起来好像要定义X和Y实体之间的关系。它具有自己的RelationQuery(围绕EFQ的包装器)和RelationQueryEndpoints,可轻松获取此类信息。


谢谢。不幸的是,我已经用entityreference定义了一些关系,所以切换到关系将是有问题的...下次将尝试:)。
mojzis 2012年

2

我知道这是一个比较老的问题,但是对于从Google接触到此问题的人来说,我想我会在这里提出另一种方法。

根据上面的描述,设置有2个实体类型,即A和B。B引用A,我假设使用实体引用。因此,如果您具有ID B,则应该在数据库中存储一个ID为A的字段。

代码说明:

  • 原始NID- $original_node->nid这将是B的ID
  • 捆绑类型- $type这应该是A的类型
  • 字段条件仅查找包含引用的字段
  • 有关如何使用的详细信息EFQ看到

// 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);
}

您还可以设置两种方式的实体引用,并向后进行相同的查询。您可以使用CER之类的模块来确保这些引用保持最新。或设置规则以使参考保持最新,我都使用了两者。


如果field_NAME_OF_FIELD为多值,是否fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=')可以使用?应该将其更改为fieldCondition('field_NAME_OF_FIELD', 'target_id', array($original_node->nid), 'IN')。找不到有关如何在多值实体参考字段上应用条件的任何信息。有什么建议吗?
排名

1
我知道这是一个旧注释,但是如果您将EntityFieldQuery的默认值= IN保留为IN,则fieldCondition('field_NAME_OF_FIELD','target_id',$ original_node-> nid)在这种情况下实际上可以工作。您可能已经知道了,但是以防万一其他人
偶然

1

一个非常动态的解决方案(也有点肮脏,但我很快就需要了它),因此您无需对引用字段的名称进行硬编码,它会自动随您将来添加的新引用字段一起处理:

在您的自定义模块中:

/**
 * 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;
}

在给定子节点的情况下需要获取父节点的位置:

$nodes = _MY_CUSTOM_MODULE_get_referencing_nodes($node);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.