Views PHP 필드를 바꾸고 커스텀 Views 핸들러로 정렬하는 방법은 무엇입니까?


11

일부 Views 성능 문제를 해결하고 모범 사례를 존중하기 위해 몇 년 전에 내 자체 사용자 지정 처리기로 구성한 일부 Views PHP 를 교체하고 싶습니다 .

예를 들어 display 에서 제외 된 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,하거나 'sort' => array('handler' => 'views_handler_sort',),또는 $this->query->add_orderby('custom', 'count_depconf_field', 'DESC');사용자 정의 정렬 핸들러로. 작동하지 않지만 'order 절'에서 알 수없는 열을 반환

  • DONE : 어떻게 얻을 수 $row->product_id$row->nid내부 query()? 하위 쿼리를 작성하려면 필요합니다. : 뷰 핸들러 필드를 추가하고 render ($ values)에서 행 값을 찾았습니다 ...

  • 완료 : 예제 핸들러의 어느 부분을 편집해야합니까? 쿼리 기능 만? 전체 예제 코드 또는 사용자 지정 부분 만 유지해야합니까?

감사합니다

답변:


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 등에 특정 구성이 필요하지 않으므로 "query"방법 만 필요합니다.

"query ()"메소드 내 에서 product_id 또는 nid 를 가져 오려면 보기 필드 핸들러에 의해 쿼리에 추가 된 기존 필드를 사용해야하고보기 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
더 일찍 반응하지 않아서 죄송합니다! 내 대답이 도움이 되길 바랍니다.하지만 모든 작업을 직접 수행했습니다. 자세한 쿼리 덕분에 하위 쿼리 별칭에 대해 몰랐습니다. 많은 사람들을 도울 것입니다.
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

뷰 정렬이 DB를 기반으로 수행되고 사용자 정의 필드 핸들러는 더미 필드의 종류이기 때문에 작동하지 않습니다. 적어도 이것이 내 결론이었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.