Xây dựng một EntityFieldQuery chọn các thực thể được tham chiếu


10

Tôi đang tìm ID của thực thể loại A và tôi biết ID của thực thể B tham chiếu A.

Tôi đã tìm thấy một vài nguồn hay về EntityFieldQuery. Tôi đã rất ngạc nhiên khi tôi nhận được kết quả từ .NET trong google :) (đó có phải là dấu hiệu của sự trưởng thành của Drupal không? :). Nhưng không quản lý để tìm thấy điều này. Xin vui lòng giúp đỡ ...

Một số nguồn:

Đây là những gì nó trông giống như với tải thực thể - bạn sẽ hiểu tôi cần truy vấn đó :) Trình bao bọc là có để thực hành là chủ yếu. Lưu ý rằng nó tải thực thể đích - khá nhiều truy vấn.

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

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

1
Một EntityFieldQuerychỉ có thể tham chiếu một tập các thực thể, nó không thể tạo mối quan hệ với các thực thể khác không may. Nó cũng chỉ có thể trả về một loại thực thể tại một thời điểm vì vậy ngay cả khi bạn có thể tạo các mối quan hệ này, kết quả sẽ không đáng tin cậy.
Clive

@Clive bạn có phiền khi thêm nó như một câu trả lời, vì vậy tôi có thể xác nhận nó không? cảm ơn :)
mojzis

Câu trả lời:


15

Bạn có thể sử dụng target_idthay vì valuetruy xuất các thực thể dựa trên ID của các thực thể được tham chiếu:

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

cảm ơn, nhưng tôi không nghĩ đó là những gì tôi đang tìm kiếm ... tôi đã cố gắng đi theo hướng khác, bằng cách này bạn sẽ biết A và tìm B :)
mojzis

2

err, là mô-đun quan hệ những gì bạn đang tìm kiếm? Nghe có vẻ như xác định mối quan hệ giữa các thực thể X và Y là những gì bạn muốn làm. nó có RelationQuery riêng (một trình bao bọc xung quanh EFQ) và RelationQueryEndpoint để dễ dàng lấy loại thông tin này.


cảm ơn. Thật không may, tôi đã xác định sẵn một vài mối quan hệ với thực thể, vì vậy việc chuyển sang quan hệ sẽ có vấn đề ... sẽ thử lần sau :).
mojzis

2

Tôi biết đây là một câu hỏi cũ hơn nhưng đối với những người nhận được câu hỏi này từ Google, tôi cho rằng tôi sẽ đưa ra một cách tiếp cận khác ở đây.

Từ mô tả ở trên, thiết lập có 2 loại thực thể, A và B. B tham chiếu A với tham chiếu thực thể mà tôi giả sử. Vì vậy, nếu bạn có id của B, bạn nên có một trường có ID của A được lưu trữ trong cơ sở dữ liệu.

Mã ghi chú:

  • NID gốc - $original_node->nidĐây sẽ là ID của B
  • Loại gói - $typeđây phải là loại A
  • Điều kiện trường chỉ tìm trường chứa tham chiếu
  • Để biết thêm thông tin về cách sử dụng EFQ, hãy xem cái này

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

Bạn cũng có thể thiết lập tham chiếu thực thể hai chiều và thực hiện cùng một truy vấn phía trên. Bạn có thể sử dụng một mô-đun như CER để đảm bảo rằng các tài liệu tham khảo được cập nhật. Hoặc thiết lập quy tắc để cập nhật tham chiếu, tôi đã sử dụng cả hai.


Nếu trường_NAME_OF_FIELD là đa giá trị sẽ fieldCondition('field_NAME_OF_FIELD', 'target_id', $original_node->nid, '=')hoạt động? nó nên được thay đổi thành fieldCondition('field_NAME_OF_FIELD', 'target_id', array($original_node->nid), 'IN'). Không thể tìm thấy bất cứ điều gì về cách áp dụng điều kiện trên trường thực thể đa trị. Bất kì lời đề nghị nào?
kiranking

1
Tôi biết đây là một nhận xét cũ nhưng nếu bạn để mặc định '=' tắt EntityFieldQuery thành IN nên fieldCondition ('field_NAME_OF_FIELD', 'target_id', $ original_node-> nid) sẽ thực sự hoạt động trong tình huống đó. Có thể bạn đã biết điều đó cho đến bây giờ nhưng chỉ cần bất kỳ ai khác vấp phải điều đó sau đó :)
burnsjeremy

1

một giải pháp khá năng động (hơi bẩn một chút nhưng tôi cần nó một cách nhanh chóng) vì vậy bạn không cần mã cứng tên cho trường tham chiếu và nó sẽ tự động được xử lý với trường tham chiếu mới mà bạn sẽ thêm trong tương lai:

trong mô-đun tùy chỉnh của bạn:

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

nơi bạn cần lấy các nút cha được cung cấp cho nút con:

$nodes = _MY_CUSTOM_MODULE_get_referencing_nodes($node);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.