참조 된 엔터티를 선택하는 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만 불행하게도 다른 엔티티들에 대한 관계를 만들 수 없습니다, 엔티티의 한 세트를 참조 할 수 있습니다. 또한 한 번에 한 유형 의 엔터티 만 반환 할 수 있으므로 이러한 관계를 만들 수 있어도 결과를 신뢰할 수 없습니다.
Clive

@Clive 답변으로 추가해 주시겠습니까? 그래서 확인할 수 있습니까? 고마워요 :)
mojzis

답변:


15

참조 된 엔티티의 ID를 기반으로 엔티티를 검색 하는 target_id대신 대신 사용할 수 있습니다 value.

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

감사합니다,하지만 난, 그게 내가 다른 방향을 잡으려고을 위해 ... 내가 찾고 있었던 무엇 당신은 B에 대한 A와 모양을 알 것입니다 이런 식으로 생각하지 않는다 :
mojzis

2

err, 당신이 찾고 있는 Relation Module 입니까? X 엔터티와 Y 엔터티 간의 관계를 정의하는 것이 원하는 것 같습니다. 자체 유형의 RelationQuery (EFQ를 감싸는 래퍼)와 RelationQueryEndpoints가있어 이러한 종류의 정보를 쉽게 얻을 수 있습니다.


감사. 불행히도 나는 entityreference와의 관계를 이미 정의 했으므로 관계로 전환하는 것이 문제가 될 것입니다 ... 다음에 시도 할 것입니다 :).
mojzis

2

나는 이것이 오래된 질문이라는 것을 알고 있지만 사람들이 구글에서 이것을 얻는다면 나는 여기에 또 다른 접근법을 던질 것이라고 생각했다.

위의 설명에서 설정에는 두 가지 엔티티 유형 A와 B가 있습니다. B는 A를 참조하는 엔티티 참조가있는 A를 참조합니다. 따라서 ID가 B 인 경우 데이터베이스에 ID가 A 인 필드가 있어야합니다.

코드 노트 :

  • Original 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'). 다중 값 엔티티 참조 필드에 조건을 적용하는 방법에 대한 정보를 찾을 수 없습니다. 어떠한 제안?
kiranking

1
나는 이것이 오래된 의견을 알고 있지만 EntityFieldQuery에서 '='를 기본값으로두면 fieldCondition ( 'field_NAME_OF_FIELD', 'target_id', $ original_node-> nid)이 실제로 해당 상황에서 작동합니다. 당신은 아마 이미 지금 쯤은 알고 있지만 나중에 :)에서 단지 넣다 다른 사람 비틀 거림
burnsjeremy

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.