จะแทนที่ฟิลด์ Views PHP และจัดเรียงตาม Custom Views Handler ได้อย่างไร?


11

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

ตัวอย่างเช่นฉันมีฟิลด์ Views PHP ที่แยกออกจากการแสดงผลด้วยการตั้งค่านั้น:

รหัสค่า:

if( $row->sticky ==1 ) {
  return 100;
} else {

  if ( isset($row->product_id) && $row->product_id != ""  ){

    $query = "SELECT COUNT(statut.entity_id) FROM field_data_field_statut_depart statut"
    . " INNER JOIN  field_data_field_product product ON statut.entity_id= product.field_product_product_id"
    . " INNER JOIN  field_data_field_date_depart depart ON statut.entity_id = depart.entity_id"
    . " WHERE product.entity_id = ". $row->nid." AND field_statut_depart_value IN (2,3) AND field_date_depart_value > NOW(); ";

    $select = db_query($query);
    $count = $select->fetchField();

    return $count; 
  }
  else {
    return -1;
  }
}

รหัสออก :

<?php print $value ; ?>`

จากนั้นฉันใช้ฟิลด์นั้นเป็นเกณฑ์การเรียงลำดับแรก ( จากน้อยไปหามาก ) ในเกณฑ์การจัดเรียง PHP ทั่วโลก:

if ($row1->php> $row2->php) return -1; else return 1;

ฉันจะขอบคุณจริงๆถ้าคุณสามารถทำให้ฉันถูกวิธี: ฉันจะสร้างฟังก์ชั่นใดในรหัสที่จะใช้กับ PHP ในฐานข้อมูล

สรุป :

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

การแก้ไข:

สิ่งที่ฉันทำจนถึง:

ไฟล์. info

files[] = views_handler_vts_products_sort.inc
files[] = includes/views_handler_vts_count_depconf_field.inc

ไฟล์โมดูล

/**
 * Implements hook_views_data().
 */
function vts_views_handler_views_data() {
  $data['custom']['table']['group'] = t('Custom');
  $data['custom']['table']['join'] = array(
    // #global is a special flag which let's a table appear all the time.
    '#global' => array(),
  );

  $data['custom']['custom_handler'] = array(
    'title' => t('Vts custom Sort Handler'),
    'help' => 'Sorts products by sticky first then by custom statut field',
    'sort' => array(
      'handler' => 'views_handler_vts_products_sort',
    ),
  );

  $data['custom']['count_depconf_field'] = array(
    'title' => t('Sum of products with status confirmed '),
    'help' => t('Calculate Sum of products with status confirmed, to order lists".'),
    'field' => array(
      'handler' => 'views_handler_vts_count_depconf_field',
      'click sortable'=> TRUE,
    ),
    /*'sort' => array(
      'handler' => 'views_handler_sort',
    ), */
  );  
  return $data;
}

function vts_views_handler_views_api() {
    return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'vts_views_handler'),
  );
}

views_handler_vts_products_sort ไฟล์

/**
 * Base sort handler that has no options and performs a simple sort.
 *
 * @ingroup views_sort_handlers
 */
class views_handler_vts_products_sort extends views_handler_sort {

  function query() {
    $this->ensure_my_table();
    // Add the field.
    $this->query->add_orderby('node', 'sticky', 'DESC');
  }
}

views_handler_vts_count_depconf_field ไฟล์

/*
 * A simple field to calculate the value I wish to order by.
 */
class views_handler_vts_count_depconf_field extends views_handler_field {

  function query() {
    //do nothing
  }

  function render($values) {
    $count = 0;

    $product_id = isset($values-> commerce_product_field_data_field_product_product_id)? $values-> commerce_product_field_data_field_product_product_id: NULL;
    if(!is_null($product_id)){

      $query = "SELECT COUNT(statut.entity_id) FROM field_data_field_statut_depart statut"
      . " INNER JOIN  field_data_field_product product ON statut.entity_id= product.field_product_product_id"
      . " INNER JOIN  field_data_field_date_depart depart ON statut.entity_id = depart.entity_id"
      . " WHERE product.entity_id = " . $values->nid . " AND field_statut_depart_value IN (2,3) AND field_date_depart_value > NOW(); ";

      $select = db_query($query);
      $count = $select->fetchField();
    }
    return $count;
  }
}

คำถามที่เหลืออยู่:

  • วิธีการสั่งซื้อโดยตัวจัดการฟิลด์ที่กำหนดเอง? ฉันพยายามเพิ่ม'click sortable'=> TRUE,OR 'sort' => array('handler' => 'views_handler_sort',),หรือ$this->query->add_orderby('custom', 'count_depconf_field', 'DESC');ลงในตัวจัดการเรียงลำดับที่กำหนดเอง ไม่มีทำงาน แต่กลับคอลัมน์ที่ไม่รู้จักใน 'ส่วนคำสั่งซื้อ'

  • DONE : ฉันจะได้รับ$row->product_idและ$row->nidภายในquery()? ฉันต้องการมันเพื่อสร้างแบบสอบถามย่อย : เพิ่มฟิลด์ตัวจัดการมุมมองและพบค่าแถวในการแสดงผล (ค่า $) ...

  • DONE : ซึ่งเป็นส่วนหนึ่งของตัวอย่างจัดการใดฉันจึงต้องแก้ไข? ฟังก์ชั่นแบบสอบถามเท่านั้น? ฉันจำเป็นต้องเก็บรหัสตัวอย่างทั้งหมดหรือเฉพาะส่วนที่กำหนดเองหรือไม่

ขอบคุณ

คำตอบ:


7

คุณต้องใช้ตัวจัดการเรียงลำดับการดู: https://api.drupal.org/api/views/handlers!views_handler_sort.inc/group/views_sort_handlers/7.x-3.x

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

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

รหัสทั้งหมดนี้จะต้องอยู่ใน "query ()" วิธีการของวัตถุของคุณ คุณต้องได้รับแบบสอบถามเช่นนี้:

SELECT table_x.field_y, ...
FROM  ...
...
...
ORDER BY row.sticky, (SELECT COUNT(statut.entity_id) 
FROM field_data_field_statut_depart statut
INNER JOIN field_data_field_product product
INNER JOIN field_data_field_date_depart depart
WHERE product.entity_id = table_x.field_y
AND field_statut_depart_value IN (2,3) 
AND field_date_depart_value > NOW())

โดยใช้ฟังก์ชันhttps://api.drupal.org/api/views/plugins%21views_plugin_query_default.inc/function/views_plugin_query_default%3A%3Aadd_orderby/7.x-3.xและฟังก์ชั่นย่อย

ข้อความค้นหาย่อยอาจได้รับการปรับให้เหมาะสมในข้อต่อ 3 ข้อขึ้นไปและบางแห่งอาจมีเงื่อนไข แต่ฉันไม่สามารถบอกได้หากไม่มีข้อความค้นหาทั้งหมด

แก้ไข

คุณขยายจากวัตถุ "views_handler" แต่คุณควรขยายจาก "views_handler_sort" โดยตรงเพื่อให้สามารถใช้รหัสเริ่มต้นสูงสุดได้สูงสุด:

class views_handler_vts_products_sort extends views_handler_sort {
  /**
   * Called to add the sort to a query.
   */
  function query() {
    $this->ensure_my_table();
    // Add the field.
    $this->query->add_orderby($this->table_alias, $this->real_field, $this->options['order']);
  }
}

ดังที่คุณเห็นด้านบนมีเพียงวิธี "แบบสอบถาม" ที่จำเป็นในกรณีของคุณเนื่องจากคุณไม่ต้องการกำหนดค่าเฉพาะใน UI ฯลฯ

ในการรับproduct_idหรือnidภายในเมธอด "query ()" ของคุณคุณต้องใช้ฟิลด์ที่มีอยู่ที่ถูกเพิ่มไปยังคิวรีโดยตัวจัดการฟิลด์มุมมอง (และกำหนดไว้ใน UI มุมมองของคุณ)

ไฟล์นี้เป็นตัวอย่างที่สมบูรณ์แบบของสิ่งที่คุณต้องการบรรลุ (คุณสามารถค้นหาได้ในเอกสารประกอบการดูเป็นไฟล์ที่มีอยู่แล้ว แต่ฉันไม่ได้รับอนุญาตให้ตั้งลิงก์เนื่องจากชื่อเสียงของฉันต่ำเกินไป):

class views_handler_sort_node_version_count extends views_handler_sort {
  function query() {
    $this->ensure_my_table();

    $this->query->add_orderby(NULL, '(SELECT COUNT(vid) FROM {node_revision} WHERE nid = {' . $this->table_alias . '}.nid)', $this->options['order'], 'sort_node_version_count');
  }
}

ดูว่าคุณสามารถปรับรหัสนี้ตามความต้องการของคุณได้ไหมและเรายินดีที่จะเห็นผลลัพธ์สุดท้าย :)


ฉันแก้ไขคำถามด้วยความคืบหน้า หากคุณต้องการตอบคำถามให้สมบูรณ์? ขอบคุณมาก
Kojo

1
เสร็จแล้วโปรดตรวจสอบและบอกฉันว่าคุณจัดการเพื่อให้การเรียงลำดับของคุณทำงานได้ดีขึ้นหรือไม่ :)
Renrhaf

ฉันไม่ดีฉันรู้ว่าเนื่องจากมุมมองอาศัยการสืบค้น DB เพื่อเรียงลำดับดูเหมือนว่าฉันจะไม่บรรลุการจัดเรียงมุมมองด้วยเขตจำลองที่เหมือนกับตัวจัดการที่สร้างขึ้น! ดังนั้นฉันจึงต้องทำงานย่อยอย่างแน่นอน!
Kojo

1
ขออภัยที่ไม่ทำปฏิกิริยาก่อนหน้านี้! ฉันหวังว่าคำตอบของฉันจะเป็นประโยชน์ แต่คุณก็ทำทุกอย่างด้วยตัวเองฉันไม่ได้รู้เรื่อง subquery alias ขอบคุณสำหรับวิธีแก้ปัญหาแบบละเอียดของคุณมันจะช่วยผู้คนได้มากมาย
Renrhaf

4

แบ่งผมด้านล่างการดำเนินการเกี่ยวกับวิธีการที่ฉันได้เพื่อแทนที่ชม PHP การเรียงลำดับตามตัวจัดการที่กำหนดเองชม

ไฟล์. info

files[] = includes/views_handler_my_custom_sort.inc

ไฟล์โมดูล

/**
 * Implements hook_views_data().
 */
function MODULE_NAME_views_data() {
  $data['custom']['table']['group'] = t('Custom');
  $data['custom']['table']['join'] = array(
    '#global' => array(),
  );

  $data['custom']['custom_handler'] = array(
    'title' => t('My custom Sort Handler'),
    'help' => 'Sorts products by sticky first then by custom statut field',
    'sort' => array(
      'handler' => 'views_handler_vts_products_sort',
    ),
  );

  return $data;
}

function MODULE_NAME_views_api() {
    return array(
    'api' => 3,
    'path' => drupal_get_path('module', 'MODULE_NAME'),
  );
}

ไฟล์ views_handler_my_custom_sort.inc

/**
 * Base sort handler that has no options and performs a simple sort.
 *
 * @ingroup views_sort_handlers
 */
class views_handler_my_custom_sort extends views_handler_sort {

  function query() {
    $this->ensure_my_table();

    $sub_query = "(SELECT COUNT(p.field_product_product_id) "
      . "FROM field_data_field_product p "
      . "LEFT JOIN field_data_field_statut_depart statut ON statut.entity_id = p.field_product_product_id "
      . "LEFT JOIN field_data_field_date_depart depart ON depart.entity_id = p.field_product_product_id  "
      . "LEFT JOIN node nod ON nod.nid = p.entity_id "
      . "WHERE nod.nid = node.nid "//This is a the obligatory condition mapping the subquery with the outer query
      . "AND field_statut_depart_value IN (2,3) "
      . "AND field_date_depart_value > NOW())";

    /* I'm timeless to write the query with the object syntax, here was a beginning
    $sub_query = db_select('field_data_field_product', 'p');
    $sub_query->addField('p', 'field_product_product_id');
    $sub_query->leftJoin('node', 'nod', 'nod.nid = p.entity_id');
    $sub_query->where("nod.nid = node.nid");
    $sub_query->countQuery(); */  

    $this->query->add_orderby('node', 'sticky', 'DESC');
    $this->query->add_orderby(NULL, $sub_query, 'DESC', 'subquery');

  }
}

คำอธิบายเล็กน้อย: หลังจากเข้าใจวิธีใช้ตัวจัดการ Views ฉันสับสนกับแบบสอบถามย่อย:

  • จับคู่กับข้อความค้นหาภายนอกเพื่อรับผลลัพธ์ "แถวต่อ" แบบไดนามิก: ตารางและคอลัมน์เดียวกัน แต่มีชื่อแทนอื่น: WHERE nod.nid = node.nid
  • ตั้งค่านามแฝงเป็นadd_orderby: ใช้$this->query->add_orderby(NULL, $sub_query, 'DESC', 'subquery');งานได้ แต่$this->query->add_orderby(NULL, $sub_query, 'DESC');ใช้ไม่ได้

จุดสุดท้ายนี้น่าแปลกใจเพราะในขณะที่SELECT TITLE FROM node ORDER BY (SELECT COUNT(field_product_product_id) FROM field_data_field_product p LEFT JOIN node nod ON nod.nid = p.entity_id WHERE nod.nid = node.nid )ทำงานในอินพุตโดยตรงของ SQL มันไม่ได้ข้ามการตั้งค่าปัจจุบัน

คุณต้องระบุชื่อแทนแบบสอบถามย่อยและแบบสอบถามสุดท้ายจะเป็นสิ่งที่ต้องการ SELECT TITLE, (SELECT COUNT(field_product_product_id) FROM field_data_field_product p LEFT JOIN node nod ON nod.nid = p.entity_id WHERE nod.nid = node.nid ) as subquery FROM node ORDER BY subquery

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.