Views PHP alanı ve özel Views işleyicisi ile sıralama nasıl değiştirilir?


11

Bazı Views performans sorunlarını gidermek ve en iyi uygulamalara saygı duymak için, bir süre önce kendi özel işleyicilerim tarafından yapılandırdığım bazı Views PHP'yi değiştirmek istiyorum .

Örneğin , bu kurulumla ekran dışında bırakılan bir Görünümler PHP alanım var :

Değer kodu:

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

Çıkış kodu :

<?php print $value ; ?>`

Sonra bir Global PHP sıralama ölçütleri , ilk sıralama ölçütleri ( artan ) olarak bu alanı kullanın :

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

Beni doğru şekilde koyabilirseniz gerçekten müteşekkir olurum: hangi işlev (ler) de veritabanında PHP ile bitirmek için aynı kodu inşa etmeliyim?

Özet:

Arama ve ilerleme, artı @Renrahf yardımından sonra, uygulamaların çoğu aşağıda ayrıntılı olarak okundu. Ama hala bir nokta ile savaşıyorum : Bir değeri hesaplamak için özel bir alan işleyicisi ekledim, ancak bu işleyici tarafından nasıl sipariş verebilirim?

Düzenlemeler:

Şimdiye kadar ne yaptım:

.info dosyası

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

Modül dosyası

/**
 * 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 dosya

/**
 * 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 dosya

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

Kalan soru:

  • özel alan işleyicisi tarafından nasıl sipariş verilir? Özel sıralama işleyicisine 'click sortable'=> TRUE,VEYA 'sort' => array('handler' => 'views_handler_sort',),VEYA eklemeyi denedim $this->query->add_orderby('custom', 'count_depconf_field', 'DESC');. Hiçbiri çalışmıyor ancak 'sipariş yan tümcesi' içinde Bilinmeyen sütun döndür

  • YAPILAN : nasıl alabilirim $row->product_idve $row->nidiçeride query()? Alt sorguyu oluşturmak için buna ihtiyacım var. : Bir görünüm işleyici alanı eklendi ve oluşturmada satır değerlerini buldu ($ değerleri) ...

  • YAPILDI : Örnek işleyicinin hangi kısmını düzenlemem gerekiyor? Yalnızca sorgu işlevi? Örnek kodun tamamını mı yoksa yalnızca özel parçaları mı tutmam gerekiyor?

teşekkür ederim

Yanıtlar:


7

Bir görünüm sıralama işleyicisi kullanmanız gerekir: https://api.drupal.org/api/views/handlers!views_handler_sort.inc/group/views_sort_handlers/7.x-3.x

Performans nedenleriyle sonuçlarınızı sıralamak için PHP'yi kullanamazsınız. PHP, yalnızca tablo sonuçlarının tamamını alırsanız sonuçları sıralamak için kullanılabilir ve bu çoğu zaman bir seçenek değildir.

Bu nedenle, kendi görünüm sıralama işleyicinizi oluşturmanız, görünümünüzde yapılandırmanız ve ardından uygun birleştirmeler yapmak için görünümler API işlevlerini kullanmanız gerekir; burada, sıralama için ihtiyacınız olan verilere ulaşmak için belki de alt sorgular. Sizin durumunuzda, belirli tarih ve tür koşullarına sahip birkaç varlık.

Tüm bu kod, nesnenizin "query ()" yönteminde bulunmalıdır. Bunun gibi bir sorgu elde etmeniz gerekir:

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 işlevini ve bir alt sorguyu kullanarak .

Alt sorgu 3 veya daha fazla eklem ve bazı durumlarda belki optimize edilebilir ama tüm sorgu olmadan söyleyemem.

DÜZENLE

"Views_handler" nesnesinden uzanır, ancak maksimum çekirdek varsayılan kodunu kullanabilmek için doğrudan "views_handler_sort" dan genişletmeniz gerekir:

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

Yukarıda görebileceğiniz gibi, kullanıcı arayüzünde vb. Herhangi bir özel yapılandırmaya ihtiyaç duymadığınız için yalnızca "sorgu" yöntemi gereklidir.

Product_id veya nid değerini "query ()" yönteminizin içine almak için, sorgulara alan görünümleri (ve görünümler arayüzünde tanımlanan) tarafından eklenen mevcut alanları kullanmanız gerekir.

Bu dosya, elde etmek istediğiniz şeyin mükemmel bir örneğidir (görünüm belgelerinde bulabilirsiniz, mevcut bir dosyadır, ancak itibarım çok düşük olduğundan bağlantıyı ayarlamama izin verilmiyor):

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

Bakalım bu kodu ihtiyaca göre uyarlayabilir misin ve sonuçtan memnun olurum :)


Sorumu ilerlemeyle düzenledim. Cevabınızı tamamlamak istiyorsanız? Çok teşekkürler
Kojo

1
Bitti, lütfen kontrol edin ve sıralamanızı başarabiliyorsanız bana söyleyin :)
Renrhaf

Benim kötü, ben görüşlerini sıralamak için DB sorgusu dayanıyor, ben asla işleyici tarafından oluşturulan gibi bir kukla alan ile bir tür görünüm elde edemeyeceğini fark ettim! Bu yüzden kesinlikle alt sorgu üzerinde çalışmak zorunda!
Kojo

1
Daha önce tepki vermediğim için üzgünüm! Umarım cevabım faydalı olmuştur, ancak tüm işi kendiniz yaptınız, alt sorgu takma adı şeyini bilmiyordum, ayrıntılı çözümünüz için teşekkürler, birçok insana yardımcı olacaktır.
Renrhaf

4

Ben özel bir Görünüm işleyicisi tarafından Görünümler PHP sıralama değiştirmek için nasıl yaptığını tam uygulama altında paylaşıyorum .

.info dosyası

files[] = includes/views_handler_my_custom_sort.inc

Modül dosyası

/**
 * 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 dosya

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

  }
}

Biraz açıklama: Views işleyicilerinin nasıl uygulanacağını anladıktan sonra, alt sorgu ile karıştım:

  • dinamik bir "sıraya göre" sonucu elde etmek için dış sorgu ile eşleştirin: aynı tablo ve sütun ancak farklı takma ad: WHERE nod.nid = node.nid
  • takma adı ayarlayın add_orderby: $this->query->add_orderby(NULL, $sub_query, 'DESC', 'subquery');çalışır, ancak $this->query->add_orderby(NULL, $sub_query, 'DESC');yapmaz

Bu son nokta şaşırtıcıydı çünkü 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 doğrudan girişinde çalışırken , mevcut kurulumda değil.

Alt sorgu takma adını belirtmeniz gerekir ve son sorgu aşağıdaki gibi olur 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

Özel bir işleyici alanında sonucu sıralamak için değerleri hesaplama girişimleri işe yaramadı, çünkü Views sıralaması DB bazında yapıldı ve özel alan işleyicisi tür bir kukla alan ... en azından bu benim sonucum oldu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.