参照されるエンティティを選択するEntityFieldQueryを作成する


10

タイプAのエンティティのIDを探しています。Aを参照するエンティティBのIDを知っています。

EntityFieldQueryに関する優れた情報源をいくつか見つけました。私はグーグルで.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それだけは残念ながら他のエンティティとの関係を作成することはできません、エンティティの1セットを参照することができます。また、一度に1つのタイプのエンティティのみを返すことができるため、これらの関係を作成できたとしても、結果は信頼できません。
クライヴ

@Cliveを回答として追加していただけませんか。確認できますか?感謝:)
mojzis 2013年

回答:


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')。複数値エンティティ参照フィールドに条件を適用する方法について何も見つかりませんでした。なにか提案を?
2015年

1
これは古いコメントですが、 '='をオフのままにすると、EntityFieldQueryのデフォルトは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);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.