เพิ่มตัวกรองเกณฑ์ในมุมมองโดยทางโปรแกรม


18

ฉันต้องการเพิ่ม / แก้ไขแบบเป็นfilter criteriaโปรแกรม

ตัวอย่างเช่นสำหรับมุมมองฉันได้เพิ่มตัวกรอง "ที่อยู่อีเมล" ซึ่งจำเป็นต้องเปลี่ยนค่าแบบไดนามิกจำเป็นต้องตั้งค่าเป็นรหัสอีเมลปัจจุบันของผู้ใช้ที่เข้าสู่ระบบ

ทำอย่างไรถึงจะบรรลุเป้าหมายนั้น? โปรดดูภาพที่แนบมาสำหรับรายละเอียดเพิ่มเติม กรุณาช่วย.

ป้อนคำอธิบายรูปภาพที่นี่

คำตอบ:


24

ใช้โมดูลDeveldpm($view)และdpm($query)หลังจากคุณใส่ "test@email.com" ลงในช่อง "ค่า" ที่พบในรูปของคุณ ดูโครงสร้างออบเจ็กต์ / อาร์เรย์ของมุมมองและเคียวรีจากเอาต์พุต devel

จากนั้นใช้ฟังก์ชันhook_views_query_alter(&$view, &$query)ในโมดูลของคุณเพื่อกำหนดเป้าหมายเงื่อนไขตัวกรองเงื่อนไข WHERE และตั้งค่าเป็นค่าที่คุณต้องการ

สิ่งที่ต้องการ:

function MYMODULE_views_query_alter(&$view, &$query) {
  global $user;
  dpm($view, __FUNCTION__);
  dpm($query, __FUNCTION__);
  if ($view->name === 'your_view_machine_name') {
    // This will only work as-is if you always have something in the filter by
    // default, I guess. This hook runs always so you could just put
    // 'test@test.com' as the email to filter by in views and this
    // will always override it. I'm sure there is a cleaner way to put
    // the filter dynamically at runtime. But i think thats more complex
    // php that customizes a view.
    //
    // The index 2 below is the index of the condition for the email filter.
    // Your $query structure may be different in your dpm() of the View $query.
    $query->where[1]['conditions'][2]['field']['value'] = $user->email;
  }
}

ขอบคุณมาก! คุณช่วยบอกฉันทีว่าฉันเขียนได้dpm($view);ที่ไหนก่อน?
Shafiul

คุณสร้างโมดูลที่กำหนดเองและวางฟังก์ชั่นด้านบนไว้เบ็ดจะเริ่มทำงานหากมีการเปิดใช้งานการดูและคุณจะเห็น $ view และ $ query ที่ด้านบนของหน้าเมื่อคุณเปิดใช้งานโมดูลที่กำหนดเองและโมดูล Devel จากนั้นเพียงแค่เปลี่ยนรหัสของฉันเพื่อให้ชื่อเครื่องของมุมมองของคุณเป็น ... และการทำให้ค่าการสืบค้น $ ทำงานกับการสืบค้นที่แน่นอนของคุณ ...
tenken

นั่นเป็นคำตอบที่ยอดเยี่ยม ใน Drupal 7 คุณทำได้จริง: $ query-> where [1] ['conditions'] [2] ['value'] = $ user-> email
Artur Kędzior

โดยส่วนตัวฉันคิดว่าคำตอบที่ใช้ hooks ด้านล่างนั้นดีกว่ามากdrupal.stackexchange.com/a/200870/9634
kbrinner

6

นี่คือทางเลือก:

$view = views_get_view('view_machine_name');
$view->init_display('default');
$view->display_handler->display->display_options['filters']['your_filter_name']['default_value'] = 'your_value';
$view->is_cacheable = FALSE;  
$view->execute();
print $view->render();

ฉันรู้ว่าคุณควรจะตั้งค่านี้โดยใช้วิธีการที่ซับซ้อนลึกลับบางอย่าง แต่ถ้าคุณเพียงแค่ต้องการการเข้าถึงที่รวดเร็วและสกปรกโดยไม่ต้องยุ่งเกี่ยวกับเรื่องนี้จะพาคุณไปที่นั่น


5

มันจะดีกว่าที่จะเปลี่ยนแปลงสิ่งเหล่านี้ใน hooks มากกว่าเวลาแสดงผลเพื่อที่คุณจะได้ไม่ทำลายประสิทธิภาพของเว็บไซต์และการแคช เอาฉันอายุจะคิดออกว่าhook_views_pre_build ()รุนแรงสายเกินไปที่คุณจะต้องhook_views_pre_view ()

ฉันพบการอ้างอิงถึงการใช้$ view-> add_item ()แต่พยายามยกตัวอย่างด้านล่างเป็นวิธีแก้ปัญหาของฉันสำหรับการกรองชุดคำศัพท์อนุกรมวิธานเพื่อรวมเฉพาะคำศัพท์บางคำเท่านั้น:

function MODULENAME_views_pre_view(&$view, &$display_id, &$args) {

  if ($view->name == 'VIEWNAME' && $display_id == 'DISPLAYID') {
    // Add all the terms of a vocabulary to the terms listing widget select field
    $vids = array();
    $vocab = taxonomy_vocabulary_machine_name_load('vocab_name');
    $vids[ $vocab->vid ] = $vocab->vid;

    // Get the existing filters
    $filters = $view->display_handler->get_option('filters');

    if (empty($filters['vid'])) {
      // There is no vid filter so we have to add it
      $view->add_item(
        $view->current_display,
        'filter',
        'taxonomy_term_data',
        'vid',
        array(
          'operator' => 'in',
          'value' => $vids,
          'group' => 1
        )
      );
    }
    else {
      // Add to pre-existing filter
      foreach($vids as $vid) {
        $filters['vid']['value'][ $vid ] = $vid;
      }
      $view->display_handler->override_option('filters', $filters);
    }
  }
}

แก้ไขหมายเหตุ : ความคิดเห็นนี้กลุ่มที่ต้องทำช่วยให้ฉันคิดออกว่าจะได้รับมุมมองที่ฟิลเตอร์ที่ใช้และจากนั้นแทนที่พวกเขาโดยใช้$view->display_handler->get_option('filters')$view->display_handler->override_option('filters', $filters);


2

ฉันมีปัญหาที่คล้ายกัน แต่สถานที่ที่พยายามส่งผ่านอาร์กิวเมนต์หลายตัวไปยังตัวกรอง ฉันใช้วิธีการ "views_get_view" แต่ส่งผ่านข้อโต้แย้งไปยังมุมมอง ฉันหวังว่ามันจะช่วยให้ใครบางคน คุณสามารถทดแทนประเภทอาร์กิวเมนต์หรือค่าสำหรับความต้องการของคุณ:

ฉันได้เพิ่มตัวกรองตามบริบทให้กับมุมมองตัวเอง (จากชุดการตั้งค่ามุมมองล่วงหน้า) คนแรกคือ "เนื้อหา: มีคำว่า taxonomy" ส่วนที่สองคือ "เนื้อหา: nid" พร้อมกับ "อนุญาตหลาย ๆ ตัวเลือก" และเลือก "ไม่รวม" ที่ทำเครื่องหมายไว้ (จากชุดฟิลด์ 'เพิ่มเติม' ในป๊อปอัพตัวกรองบริบท)

args [] = '1'; // รหัสประจำตัว
args [] = '1 + 2 + 3'; // Node ID ที่ต้องการยกเว้น / รวม

$ view = views_get_view ($ view_name);
$ View-> init ();
$ View-> set_display ($ จอแสดงผล);
$ View-> set_arguments ($ args);
$ View-> รัน ();
$ View-> ผล

อัปเดต: ฉันลืมที่จะพูดถึงภายในค่าตัวกรองตามบริบทคุณอาจต้องเลือกรหัส php และส่งคืนอาร์กิวเมนต์ของมุมมองที่ส่งผ่านเช่น

ส่งคืน $ view-> args [1];

1

ใน Drupal 8 คุณสามารถใช้ViewExecutable::setHandler($display_id, $type, $id, $item)เพื่อตั้งตัวกรองโดยทางโปรแกรม


4
คำตอบนี้อาจจะละเอียดกว่านี้อีกเล็กน้อยเกี่ยวกับสาเหตุของการทำงาน ฉันมักจะชอบที่จะเชื่อมโยงและพูดถึงหน้าเอกสาร สิ่งนี้จะช่วยให้ผู้ถามเรียนรู้เพิ่มเติมเกี่ยวกับ Drupal API และช่วยค้นหาข้อมูลด้วยตนเองในอนาคต
mradcliffe

1

นี่คือตัวอย่างเกี่ยวกับวิธีเพิ่มเกณฑ์การกรองโดยทางโปรแกรมใน Drupal 8:

/**
 * @param ViewExecutable $view
 * @param QueryPluginBase $query
 *
 * Sets a custom custom filter criteria (takes current language into account)
 */
function MODULE_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {
  if ($view->storage->id() === 'my_view_id') {
    $query->addWhere(0, 'node__field_custom_criteria.field_custom_criteria_value', \Drupal::languageManager()->getCurrentLanguage()->getId(), '=');
  }
}

แบบสอบถามด้านบนจะเพิ่มเกณฑ์ที่กรองโหนดที่field_custom_criteriaเขตข้อมูลเท่ากับภาษาที่เลือกในปัจจุบัน

ข้อมูลเพิ่มเติมสามารถพบได้ในเอกสาร: hook_views_query_alter


0

จากคำตอบของ@ Duncanmoo ด้านบนที่ฉันรู้สึกว่าดีที่สุดฉันได้เพิ่มตัวกรองต่อไปนี้ในมุมมองของฉัน - คิดว่าสิ่งเหล่านี้จะเป็นตัวอย่างที่มีประโยชน์ในกรณีที่คุณไม่ได้พยายามกรองตาม taxonomy ที่อ้างอิง แต่เป็นนิติบุคคลที่อ้างอิงหรือ NID:

function [MYMODULE]_views_pre_view(&$view, &$display_id, &$args) {
  if (($view->name == '[your view name]') && ($display_id == '[your display id]')) {
    // Get referenced service - example for entity reference.
    $node = menu_get_object();
    $node_wrapper = entity_metadata_wrapper('node', $node->nid);
    $referenced_service = $node_wrapper->field_service_ref->value();
    // Add service id as a filter to view.
    $filters = $view->display_handler->get_option('filters');
    if (empty($filters['field_service_ref_target_id'])) {
      // Only display operations nodes that reference the same service.
      $view->add_item(
        $display_id,
        'filter',
        'field_data_field_service_ref',
        'field_service_ref_target_id',
        array(
          'operator' => '=',
          'value' => ['value' => $referenced_service->id],
          'group' => 1
        )
      );
    }
    // Add nid as a filter to view - example for NID filter
    if (empty($filters['nid'])) {
      // Don't include current operation in list of related operations.
      $view->add_item(
        $display_id,
        'filter',
        'node',
        'nid',
        array(
          'operator' => '!=',
          'value' => ['value' => $node->nid],
          'group' => 1
        )
      );
    }
  }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.