it-swarm.com.de

Wie ersetze ich Views PHP Feld und sortiere nach benutzerdefiniertem Views Handler?

Um einige Leistungsprobleme von Views zu beheben und Best Practices zu respektieren, möchte ich einige ersetzen Views PHP Ich habe vor einiger Zeit durch meine eigenen benutzerdefinierten Handler konfiguriert.

Zum Beispiel habe ich ein Views PHP Feld, von der Anzeige ausgeschlossen mit diesem Setup:

Wertcode:

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

Ausgabecode :

<?php print $value ; ?>`

Dann verwende ich dieses Feld als erstes Sortierkriterium ( aufsteigend) in einem globalen PHP Sortierkriterium:

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

Ich wäre Ihnen sehr dankbar, wenn Sie mich auf den richtigen Weg bringen könnten: In welchen Funktionen soll ich denselben Code erstellen, um am Ende PHP in der Datenbank) zu erhalten?

Zusammenfassung :

Nach der Suche und dem Fortschritt sowie der @ Renrahf-Hilfe scheint der größte Teil der Implementierung in Ordnung zu sein (siehe unten). Aber ich kämpfe immer noch mit einem Punkt : Ich habe einen benutzerdefinierten Feldhandler hinzugefügt, um einen Wert zu berechnen, aber wie kann ich nach diesem Handler bestellen?

Bearbeitungen:

Was ich bisher gemacht habe:

. Info-Datei

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

Moduldatei

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

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

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

Verbleibende Frage:

  • wie bestelle ich mit dem benutzerdefinierten Feldhandler? Ich habe versucht, 'click sortable'=> TRUE, OR 'sort' => array('handler' => 'views_handler_sort',), OR $this->query->add_orderby('custom', 'count_depconf_field', 'DESC'); in den benutzerdefinierten Sortierhandler einzufügen. Keiner funktioniert Geben Sie jedoch die Spalte Unbekannt in der 'order-Klausel' zurück.

  • [~ # ~] erledigt [~ # ~]: Wie kann ich $row->product_id Und $row->nid In query()? Ich brauche es, um die Unterabfrage zu erstellen.: Ein Views-Handler-Feld wurde hinzugefügt und die Zeilenwerte in render ($ values) gefunden ...

  • [~ # ~] erledigt [~ # ~]: Welcher Teil des Beispielhandlers erledigt Ich muss bearbeiten? Nur die Abfragefunktion? Muss ich den gesamten Beispielcode oder nur die benutzerdefinierten Teile behalten ?

Vielen Dank

11
Kojo

Sie müssen einen Views Sort Handler verwenden: https://api.drupal.org/api/views/handlers!views_handler_sort.inc/group/views_sort_handlers/7.x-3.x

Sie können PHP zum Sortieren Ihrer Ergebnisse aus Leistungsgründen nicht verwenden. PHP kann nur zum Sortieren von Ergebnissen verwendet werden, wenn Sie die gesamten Tabellenergebnisse abrufen, und das ist Meistens keine Option.

Sie müssen also Ihren eigenen Ansichts-Sortierhandler erstellen, ihn in Ihrer Ansicht konfigurieren und dann die Ansichten-API-Funktionen verwenden, um die richtigen Verknüpfungen herzustellen, wobei möglicherweise sogar Unterabfragen die Daten enthalten, die Sie für Ihre Sortierung benötigen. In Ihrem Fall eine Reihe von Entitäten mit bestimmten Datums- und Typbedingungen.

Der gesamte Code muss sich in der Methode "query ()" Ihres Objekts befinden. Sie müssen eine Abfrage wie folgt durchführen:

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

Mit der Funktion https://api.drupal.org/api/views/plugins%21views_plugin_query_default.inc/function/views_plugin_query_default%3A%3Aadd_orderby/7.x-3.x und einer Unterabfrage.

Die Unterabfrage kann in 3 oder mehr Gelenken und einigen Bedingungen optimiert werden, aber ich kann es nicht ohne die gesamte Abfrage sagen.

[~ # ~] edit [~ # ~]

Sie erstrecken sich vom Objekt "views_handler", sollten sich jedoch direkt vom Objekt "views_handler_sort" erstrecken, um das Maximum des Standard-Kerncodes verwenden zu können:

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

Wie Sie oben sehen können, wird in Ihrem Fall nur die "Abfragemethode" benötigt, da Sie keine spezifischen Konfigurationen in der Benutzeroberfläche usw. benötigen.

Um die product_id oder nid in Ihre "query ()" - Methode zu integrieren müssen Sie vorhandene Felder verwenden, die der Abfrage von Views-Feldhandlern hinzugefügt wurden (und in Ihrer Views-Benutzeroberfläche definiert wurden).

Diese Datei ist das perfekte Beispiel für das, was Sie erreichen möchten (Sie finden sie in der Ansichtsdokumentation, es ist eine vorhandene, aber ich darf den Link nicht setzen, da mein Ruf zu niedrig ist):

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

Sehen Sie, ob Sie diesen Code an Ihre Bedürfnisse anpassen können, und ich freue mich über das Endergebnis :)

7
Renrhaf

Ich teile unten die vollständige Implementierung mit, wie ich Views ersetzen PHP Sortieren durch einen benutzerdefinierten Views-Handler.

.infodatei

files[] = includes/views_handler_my_custom_sort.inc

Moduldatei

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

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

  }
}

Eine kleine Erklärung: Nachdem ich verstanden hatte, wie Views-Handler implementiert werden, wurde ich mit der Unterabfrage verwechselt:

  • ordnen Sie es der äußeren Abfrage zu, um ein dynamisches "row by" -Ergebnis zu erhalten: gleiche Tabelle und Spalte, aber unterschiedlicher Alias: WHERE nod.nid = node.nid
  • setzen Sie den Alias ​​in add_orderby: $this->query->add_orderby(NULL, $sub_query, 'DESC', 'subquery'); funktioniert, $this->query->add_orderby(NULL, $sub_query, 'DESC'); jedoch nicht

Dieser letzte Punkt war überraschend, da 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 ) zwar in der direkten SQL-Eingabe funktioniert, jedoch nicht im aktuellen Setup.

Sie müssen den Unterabfrage-Alias ​​angeben, und die endgültige Abfrage lautet etwa 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

Die Versuche, die Werte zum Sortieren des Ergebnisses in einem benutzerdefinierten Handlerfeld zu berechnen, haben nicht funktioniert, da die Sortierung der Ansichten auf DB-Basis erfolgt und der benutzerdefinierte Feldhandler eine Art Dummy-Feld ist ... zumindest war dies meine Schlussfolgerung.

4
Kojo