Wie erstelle ich eine Vereinigung von zwei Ansichten?


36

Ich versuche, die Knoten und Kommentare eines Benutzers nach "Post-Datum" zu sortieren. Dieser Beitrag enthält Links zu Sandbox-Projekten für D6, für 7 gibt es jedoch keine Links.

Dieser Beitrag enthält ein Beispiel für die Verwendung von hook_views_pre_execute () und einer SQL-UNION in D6. Dies funktioniert nicht für D7 mit Ansichten 3.

Ich bin auf den Kommentar von merlinofchaos gestoßen

Da wir jetzt den neuen Abfrage-Generator von Drupal verwenden, ist die Abfrage ein SelectQuery-Objekt, das Sie ändern oder ersetzen müssen. Weitere Informationen finden Sie in der neuen Datenbankebene von Drupal 7.

Hat jemand ein Beispiel für diese oder eine andere Lösung, um zwei Ansichten zu kombinieren?


Dies ist eher eine Idee als eine echte Antwort: Sie sollten in der Lage sein, eine Ansicht basierend auf Benutzern zu erstellen, die sowohl die Knoten als auch die Kommentare verknüpft (und nicht, dass beide nur Entitäten sind :). Bei meinem ersten Versuch ist mir dies nicht gelungen, da Views nicht die Beziehung zwischen Benutzer und Kommentar bieten. Aber das sollte leicht zu ändern sein. (oder ich habe nur etwas vergessen).
Mojzis

Ich denke, es ist die gleiche Antwort wie unten: kt würde zwei kontextbezogene Filter erfordern (content.author = angemeldeter Benutzer ODER comment.author = angemeldeter Benutzer).
uwe

Ich glaube nicht :) Ich meine eine Ansicht basierend auf Benutzern, die Knoten und Kommentare verbinden. aber ich habe das gefühl, dass es ein problem mit der beziehung zwischen benutzer und kommentar gibt - ich habe es nicht geschafft, die kommentare anzuzeigen.
Mojzis

Ich rate nur, aber können Sie searchapi nicht verwenden, um mehrere Entitätstypen gleichzeitig zu indizieren? Wenn Sie das haben und ein Feld haben, das von beiden Teilen verwendet wird, können Sie damit eine Ansicht wie diese erstellen.
Daniel Wehner

1
Es gibt ein Sandbox-Projekt 'Views Unionize' für Drupal 7, bitte überprüfen Sie drupal.org/sandbox/jalama/1785294 ,
Anoop Joseph

Antworten:


15

Hier ist ein funktionierendes und getestetes Beispiel:

/**
 * Implements hook_views_pre_execute().
 */
function mymodule_views_pre_execute(view &$view) {
  if ($view->name == 'my_view') {
    $query1 = &$view->build_info['query'];

    // Basic setup of the second query.
    $query2 = db_select('another_table', 'at')
      ->condition('some_field', 0, '>')
      ->condition('some_other_field', 12345);

    // The number of fields (and their aliases) must match query1.
    // Get the details with:
    // dpm($query1->getFields());
    $query2->addField('at', 'some_field', 'alias1');
    $query2->addField('at', 'some_other_field', 'alias2');
    $query2->addField('at', 'some_other_field2', 'alias3');
    $query2->addField('at', 'some_other_field3', 'alias4');

    // Verify that queries are very similar.
    // dpq($query1);
    // dpq($query2);

    // Matrimony.
    $query1 = $query2->union($query1, 'UNION ALL');

    // Manual test.
    // dpm($query1->execute()->fetchAll());

  }
}

Dies funktioniert für die meisten Ansichten. Wie auch immer, einige Stil-Plugins können ausgefallene Dinge tun, die mit dieser Technik nicht funktionieren (Kalendermodul, das ich gerade betrachte).



2

Am Ende habe ich db_query () verwendet, um die SQL-UNIONs zu erstellen und sie dann mithilfe der theme () -Funktion in ein Tabellenlayout mit Pagern zu rendern.

Für den Benutzer sieht es aus wie Standardansichten. Der andere Vorteil war, dass ich die Abfrage sehr optimieren konnte. Ich zeige "Aktivitäten meines Freundes" und wenn Sie Ansichten dafür verwenden würden, würde dies eine Liste Ihrer Freunde erstellen und diese in einer SQL "IN" -Klausel verwenden, die sehr langsam ist, wenn Sie mehr als 50 oder 100 Datensätze haben.

Ich könnte diese Freundesliste auf diejenigen beschränken, die in den letzten x Tagen auf der Website eingeloggt waren.

Dies ist ein Codebeispiel:

  // Two queries are required (friendships can be represented in 2 ways in the
  // same table). No point making two db calls though so a UNION it is.

  // Build up the first query.
  $query = db_select('flag_friend', 'f')
    ->condition('f.uid', $account->uid)
    ->condition('u.login', $timestamp, '>');
  $query->addExpression('f.friend_uid', 'uid');
  $query->innerJoin('users', 'u', 'u.uid = f.friend_uid');

  // Build up the second query.
  $query2 = db_select('flag_friend', 'f')
    ->condition('f.friend_uid', $account->uid)
    ->condition('u.login', $timestamp, '>');
  $query2->addExpression('f.uid', 'uid');
  $query2->innerJoin('users', 'u', 'u.uid = f.uid');

  // Return the results of the UNIONed queries.
  return $query->union($query2)->execute()->fetchCol();

1

Auf diese Weise habe ich in Zukunft zwei Ansichten kombiniert, die auf derselben Tabelle basieren. Die gleichen Prinzipien sollten auch für Ansichten gelten, die auf verschiedenen Tabellen mit der gleichen Anzahl von Feldern basieren.

Im folgenden Fall wird nur ID ausgewählt, da das Format auf gerenderte Entität gesetzt ist. Wenn Sie jedoch mit Feldern arbeiten, können Sie der Abfrage, die weniger Felder enthält, immer zusätzliche Dummy-Felder hinzufügen, da ich unten einen Zeitstempel hinzugefügt habe.

/**
 * Implements hook_views_pre_execute().
 */
function MY_MODULE_views_pre_execute(&$view) {
  if ($view->name == 'VIEW_1' && $view->current_display == 'DISPLAY_OF_VIEW_1') {

    $view2 = views_get_view('VIEW_2');
    $view2->build('DISPLAY_OF_VIEW_2');

    $view->build_info['query']
    ->fields('table_alias', array('timestamp'))
    ->union(
        $view2->build_info['query']
        ->range()
        ->fields('table_alias', array('timestamp'))
        ->orderBy('timestamp', 'DESC')
    );

    $view->build_info['count_query']
    ->union(
        $view2->build_info['count_query']
        ->range()
    );
  };
}

0

Ich stelle mir so etwas vor:

/** 
* Implements hook_views_pre_execute().
*/     
function mymodule_views_pre_execute(&$view) {
  if ($view->name == 'myview') {
    $query = $view->query;
    $other_view = views_get_view('otherview');
    $other_query = $other_view->query;
    $query = $query->union($other_query);
    $view->query = $query;
  }
}

Obwohl ich es nicht getestet habe.

Einige Links, die helfen können:

http://api.drupal.org/api/drupal/includes!database!select.inc/function/SelectQueryInterface%3A%3Aunion/7

http://drupal.org/node/557318#comment-1991910


1
Dies scheint nicht vollständig zu funktionieren. $ view-> query ist das Zwischenobjekt, mit dem Views die Abfrage erstellt. Die SelectQuery lautet $ view-> build_info ['query']. Wenn Sie entsprechend bearbeiten, kann ich nicht über einen Fehler "Schwerwiegender Fehler: Aufruf der undefinierten Methode SelectQuery :: render_pager ()" hinaus.
mpdonadio

1
Der Datenbanktestcode enthält Beispiele für Gewerkschaften api.drupal.org/api/drupal/… und api.drupal.org/api/drupal/…
mikeytown2


Dies funktioniert möglicherweise nur, wenn beide Ansichten nahezu identisch sind.
Dalin

0

Ich bin auf ein Modul namens Ansichten Feldansicht gestoßen , mit dem Sie eine Ansicht als Feld in eine andere Ansicht einbetten können. Ich habe das selbst noch nicht ausprobiert, aber es könnte für Sie hilfreich sein.


2
Während die Ansichtsfeldansicht in der Tat sowohl Kommentare als auch Knoten enthalten kann, glaube ich nicht, dass es eine Möglichkeit gibt, die Felder nur innerhalb dieser Felder zu sortieren.
Letharion

0

Das EntityFieldQuery Views-Backend unterstützt die gleichzeitige Abfrage mehrerer Entitätstypen. Es sollte also möglich sein, sowohl nach Knoten als auch nach Kommentaren zu fragen. Beide Entitätstypen verwenden eine uidEigenschaft, um eine Verknüpfung zu ihrem Autor herzustellen. Auf API-Ebene sollte daher EntityFieldQuery :: propertyCondition () verwendet werden können, um die Knoten und Kommentare eines einzelnen Benutzers auszuwählen. Ich denke, das Ansichten-Backend bietet die gleiche Funktion.


Es sieht so aus, als hätten sie gerade die Funktion zum Abfragen mehrerer Entitäten entfernt: drupal.org/node/1564740
uwe

0

Ein anderer Ansatz könnte darin bestehen, Feeds mit Knoten und Kommentaren zu erstellen (mit einem kontextbezogenen Filter der Benutzerkennung in der URL) und die beiden Feeds dann zu einem neuen Feed zu kombinieren und nach Post-Datum anzuzeigen.


-2

Verwendet Global: PHP Felder? Sie können sie verwenden, um eine Ansicht mit Klebeband zusammenzufügen, in der beide kombiniert werden.

Erstellen Sie eine Inhaltsansicht mit den Feldern Inhalt: Titel und Inhalt: Kommentare (von der Anzeige ausgeschlossen).

Fügen Sie ein PHP-Feld hinzu, das berechnet, welches aktueller ist, das Datum der letzten Aktualisierung oder das Datum des letzten Kommentars des Benutzers, und legen Sie den Wert des Felds auf dieses Datum fest. Fügen Sie dieses Feld als Sortierbedingung hinzu.

Fügen Sie ein ähnliches Feld hinzu, das entweder einen Link zum Kommentar oder zum Knoten ausgibt.

Klingt gut für mich!


interessante Idee. Es wären zwei Kontextfilter erforderlich (content.author = angemeldeter Benutzer ODER comment.author = angemeldeter Benutzer).
uwe

In der Hoffnung, die epische Genesung auf diesem zu bekommen ...;)
Johnathan Elmore

2
Der Performance-Hit von diesem Ansatz wäre unheimlich. Die potenzielle Anzahl der durchgeführten Datenbankabfragen könnte an astronomische Grenzen stoßen.
Rider_X
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.