สร้าง EntityFieldQuery ที่เลือกเอนทิตีที่อ้างอิง


10

ฉันกำลังมองหา ID ของกิจการของประเภท A และฉันรู้ว่ารหัสของกิจการ B ที่อ้างอิงก

ฉันพบแหล่งข้อมูลที่ดีเกี่ยวกับ EntityFieldQuery ฉันประหลาดใจที่ฉันได้รับผลลัพธ์จาก. NET ใน google :) (มันเป็นสัญญาณของวุฒิภาวะของ 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สามารถอ้างอิงได้เพียงหนึ่งชุดของหน่วยงานก็ไม่สามารถสร้างความสัมพันธ์กับหน่วยงานอื่น ๆ ที่น่าเสียดาย นอกจากนี้ยังสามารถส่งคืนเอนทิตีได้ครั้งละหนึ่งประเภทเท่านั้นแม้ว่าคุณจะสามารถสร้างความสัมพันธ์เหล่านี้ได้ผลลัพธ์ก็จะไม่น่าเชื่อถือ
ไคลฟ์

@ ไคลเอนต์คุณจะรังเกียจการเพิ่มว่าเป็นคำตอบดังนั้นฉันสามารถยืนยันได้หรือไม่ ขอบคุณ :)
mojzis

คำตอบ:


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 ของตัวเอง (wrapper รอบ EFQ) และ RelationQueryEndpoints เพื่อรับข้อมูลประเภทนี้ได้อย่างง่ายดาย


ขอบคุณ น่าเสียดายที่ฉันได้กำหนดความสัมพันธ์บางอย่างกับเอนทิตีการอ้างอิงดังนั้นการเปลี่ยนไปใช้ความสัมพันธ์จะเป็นปัญหา ... จะลองอีกครั้ง :)
mojzis

2

ฉันรู้ว่านี่เป็นคำถามที่เก่ากว่า แต่สำหรับผู้ที่ได้รับสิ่งนี้จาก Google ฉันคิดว่าฉันจะใช้วิธีการอื่นในที่นี้

จากคำอธิบายข้างต้นการตั้งค่ามีเอนทิตี 2 ประเภท A และ B. B อ้างอิง A พร้อมการอ้างอิงเอนทิตีที่ฉันกำลังสมมติ ดังนั้นหากคุณมี ID ของ B คุณควรมีฟิลด์ที่มี ID ของ A เก็บไว้ในฐานข้อมูล

หมายเหตุของรหัส:

  • NID ดั้งเดิม - $original_node->nidนี่จะเป็น ID ของ B
  • ประเภทบันเดิล - $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 ค่าเริ่มต้นเป็น IN ดังนั้น 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.