Làm cách nào để thay thế trường Xem PHP và sắp xếp theo trình xử lý Lượt xem tùy chỉnh?


11

Để giải quyết một số vấn đề về hiệu suất của Chế độ xem và tôn trọng các thực tiễn tốt nhất, tôi muốn thay thế một số Chế độ xem PHP mà tôi đã cấu hình trước đây bằng các trình xử lý tùy chỉnh của riêng tôi .

Chẳng hạn, tôi đã có trường PHP Chế độ xem, được loại trừ khỏi màn hình , với thiết lập đó:

Mã giá trị:

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

Mã đầu ra :

<?php print $value ; ?>`

Sau đó, tôi sử dụng trường đó làm tiêu chí sắp xếp đầu tiên ( tăng dần ), trong tiêu chí sắp xếp PHP toàn cầu:

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

Tôi thực sự biết ơn nếu bạn có thể đưa tôi đi đúng hướng: trong (các) chức năng nào tôi sẽ xây dựng cùng một mã để kết thúc với PHP trong cơ sở dữ liệu?

Tóm lược :

Sau khi tìm kiếm và tiến triển, cộng với sự giúp đỡ của @Renrahf, hầu hết việc thực hiện có vẻ ổn, chi tiết bên dưới. Nhưng tôi vẫn chiến đấu với một điểm : Tôi đã thêm trình xử lý trường tùy chỉnh để tính giá trị, nhưng làm cách nào tôi có thể đặt hàng bằng trình xử lý đó?

Chỉnh sửa:

Những gì tôi đã làm cho đến nay:

tập tin .info

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

Tập tin mô-đun

/**
 * 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 tập tin

/**
 * 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 tập tin

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

Câu hỏi còn lại:

  • Làm thế nào để đặt hàng bởi trình xử lý trường tùy chỉnh? Tôi đã thử thêm 'click sortable'=> TRUE,OR 'sort' => array('handler' => 'views_handler_sort',),HOẶC $this->query->add_orderby('custom', 'count_depconf_field', 'DESC');vào trình xử lý sắp xếp tùy chỉnh. Không có tác dụng nào nhưng trả về cột Không xác định trong 'mệnh đề thứ tự'

  • DONE : Làm thế nào tôi có thể vào $row->product_id$row->nidbên trong query()? Tôi cần nó để xây dựng các truy vấn con. : Đã thêm trường xử lý lượt xem và tìm thấy các giá trị hàng trong kết xuất (giá trị $) ...

  • DONE : Tôi phải chỉnh sửa phần nào của trình xử lý ví dụ? Hàm truy vấn chỉ? Tôi có cần giữ toàn bộ mã ví dụ hay chỉ các phần tùy chỉnh không?

Cảm ơn bạn

Câu trả lời:


7

Bạn cần sử dụng trình xử lý sắp xếp lượt xem: https://api.drupal.org/api/view/handlers!view_handler_sort.inc/group/view_sort_handlers/7.x-3.x

Bạn không thể sử dụng PHP để sắp xếp kết quả của mình vì lý do hiệu suất. PHP chỉ có thể được sử dụng để sắp xếp kết quả nếu bạn tìm nạp toàn bộ kết quả bảng và đó không phải là một tùy chọn hầu hết thời gian.

Vì vậy, bạn cần tạo trình xử lý sắp xếp chế độ xem của riêng mình, định cấu hình nó trong chế độ xem của bạn và sau đó sử dụng các hàm API của chế độ xem để thực hiện các phép nối phù hợp, trong đó, thậm chí có thể truy vấn các dữ liệu bạn cần để sắp xếp. Trong trường hợp của bạn, một số thực thể có điều kiện ngày và loại cụ thể.

Tất cả mã này phải nằm trong phương thức "query ()" của đối tượng của bạn. Bạn cần đạt được một truy vấn như thế này:

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

Bằng cách sử dụng hàm https://api.drupal.org/api/view/plugins%21view_plugin_query_default.inc/feft/view_plugin_query_default%3A%3Aadd_orderby/7.x-3.x và một truy vấn con.

Truy vấn con có thể được tối ưu hóa trong 3 khớp trở lên và một số điều kiện có thể nhưng tôi không thể biết nếu không có toàn bộ truy vấn.

BIÊN TẬP

Bạn mở rộng từ đối tượng "Views_handler" nhưng bạn nên trực tiếp mở rộng từ "Views_handler_sort" để có thể sử dụng tối đa mã mặc định lõi:

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']);
  }
}

Như bạn có thể thấy ở trên, chỉ cần phương thức "truy vấn" trong trường hợp của bạn vì bạn không cần bất kỳ cấu hình cụ thể nào trong UI, v.v.

Để có được Product_id hoặc nid bên trong phương thức "query ()" của bạn, bạn phải sử dụng các trường hiện có được thêm vào truy vấn bởi các trình xử lý trường xem (và được xác định trong UI view của bạn).

Tệp này là ví dụ hoàn hảo về những gì bạn muốn đạt được (bạn có thể tìm thấy nó trong tài liệu xem, nó là một tệp hiện có nhưng tôi không được phép đặt liên kết vì danh tiếng của tôi quá thấp):

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

Xem bạn có thể điều chỉnh mã này theo nhu cầu của mình không và tôi sẽ rất vui khi thấy kết quả cuối cùng :)


Tôi đã chỉnh sửa câu hỏi của mình với sự tiến bộ. Nếu bạn muốn hoàn thành câu trả lời của bạn? Cảm ơn rất nhiều
Kojo

1
Xong, vui lòng kiểm tra và cho tôi biết nếu bạn quản lý để sắp xếp công việc của mình :)
Renrhaf

Thật tệ, tôi nhận ra rằng vì các lượt xem dựa vào truy vấn DB để sắp xếp, nên có vẻ như tôi sẽ không bao giờ đạt được một loại lượt xem với trường giả giống như trường được tạo bởi trình xử lý! Vì vậy, tôi chắc chắn phải làm việc trên các truy vấn con!
Kojo

1
Xin lỗi vì đã không phản ứng sớm hơn! Tôi hy vọng câu trả lời của tôi hữu ích nhưng bạn đã tự mình làm tất cả công việc, tôi không biết gì về bí danh truy vấn phụ, nhờ giải pháp chi tiết của bạn, nó sẽ giúp được rất nhiều người.
Renrhaf

4

Tôi chia sẻ bên dưới triển khai đầy đủ về cách tôi đã làm để thay thế Chế độ xem PHP sắp xếp bằng trình xử lý Lượt xem tùy chỉnh .

tập tin .info

files[] = includes/views_handler_my_custom_sort.inc

Tập tin mô-đun

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

tập tin lượt xem_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');

  }
}

Một chút giải thích: sau khi hiểu cách triển khai trình xử lý Lượt xem, tôi đã nhầm lẫn với truy vấn con:

  • ánh xạ nó với truy vấn bên ngoài để có kết quả "hàng theo" động: cùng bảng và cột nhưng bí danh khác nhau: WHERE nod.nid = node.nid
  • đặt bí danh trong add_orderby: $this->query->add_orderby(NULL, $sub_query, 'DESC', 'subquery');công trình, nhưng $this->query->add_orderby(NULL, $sub_query, 'DESC');không

Điểm cuối cùng này là đáng ngạc nhiên bởi vì trong khi 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 )hoạt động trong đầu vào trực tiếp SQL, nó không qua thiết lập hiện tại.

Bạn cần chỉ định bí danh truy vấn con và truy vấn cuối cùng sẽ giống như 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

Việc cố gắng tính toán các giá trị để sắp xếp kết quả trong trường trình xử lý tùy chỉnh, không hoạt động vì việc sắp xếp Lượt xem được thực hiện trên cơ sở DB và trình xử lý trường tùy chỉnh là loại trường giả ... ít nhất đây là kết luận của tôi.

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.