Widoki3 i podzapytania?

12

Mam widok, który generuje zapytanie, które wykonuje wiele połączeń. To powoduje sprzężenie kartezjańskie i muszę „przekonwertować” sprzężenia na podzapytania.

Przejrzałem dokumentację, wyniki wyszukiwania Google i inne źródła, ale nie jestem w stanie znaleźć żadnego porządnego opisu tego, jak skonfigurować Widoki do wykonywania podkwerend. Użyłem hook_views_data () do skonfigurowania relacji (które są teraz realizowane jako sprzężenia). Czy w jakiś sposób można zdefiniować podzapytania za pomocą hook_views_data (), czy też muszę zastosować inne podejście?

Wszelkie porady są mile widziane!

sbrattla
źródło

Odpowiedzi:

5

Spojrzałem dalej, ale tak naprawdę nie mogłem znaleźć żadnej dokumentacji opisującej to.

Potrzebowałem sposobu, aby połączyć tabelę użytkowników z dwoma innymi tabelami przechowującymi dane dla użytkowników. Jednak dwie pozostałe tabele są w relacji „jeden do wielu” z tabelą użytkowników, co oznacza, że ​​skończę z kartezjańskim złączeniem, jeśli spróbuję dołączyć do tabeli użytkowników z tymi dwiema tabelami w tym samym czasie . Ponieważ jednak wszystko, czego potrzebuję, to policzyć liczbę rekordów w dwóch innych tabelach powiązanych z danym użytkownikiem, podzapytanie powinno być w stanie załatwić sprawę. Nie mogłem jednak znaleźć żadnej dokumentacji dotyczącej widoków i podkwerend - oto co zrobiłem.

  1. Utworzono dwa pola zastępcze

Utworzyłem dwa fikcyjne pola (które nazywam „pobierającymi” i „nasłuchującymi”) za pomocą hook_views_data (). Definicja pola znajduje się poniżej.

function hook_views_data() {

  $data['users'] = array(
    'downloads' => array(
      'title' => t('Downloads'),
      'field' => array(
        'handler' => 'views_handler_field_numeric',
        'click sortable' => TRUE,
      ),
      'filter' => array(
        'handler' => 'views_handler_filter_numeric',
      ),
      'sort' => array(
        'handler' => 'views_handler_sort',
      ),
    ),
    'listens' => array(
      'title' => t('Listens'),
      'field' => array(
        'handler' => 'views_handler_field_numeric',
        'click sortable' => TRUE,
      ),
      'filter' => array(
        'handler' => 'views_handler_filter_numeric',
      ),
      'sort' => array(
        'handler' => 'views_handler_sort',
      ),
    )
  ),
);

Teraz, gdy skonfigurujesz widok dla użytkowników, pojawią się pola „Pobrane” i „Słuchaj”. Jednak próba uruchomienia zapytania spowoduje błąd, ponieważ pola zastępcze są przecież polami zastępczymi. Oni nie istnieją. Jedynym celem tych pól jest zasygnalizowanie naszej implementacji hook_views_query_alter (), że musi wykonać kilka wymian.

  1. Zaimplementuj hook_views_query_alter ()

Sztuczka polega na sprawdzeniu, czy dane zapytanie zawiera pola „Pobrane” lub „Słuchane”. Jeśli tak, usuniemy pola z zapytania i zastąpimy je podzapytaniami. Implementacja tej funkcji przebiega jak poniżej.

function mta_views_query_alter(&$view, &$query) {

  foreach ($query->fields as $field_key => &$field_values) {
    if ($field_values['table'] == 'users') {

      switch ($field_values['field']) {
        case 'downloads':
          unset($query->fields[$field_key]);
          $query->add_field(null, "(SELECT COUNT(*) FROM {fileusage} fu WHERE fu.externaluser = {users}.uid AND fu.action = 0)", $field_key);
          break;
        case 'listens':
          unset($query->fields[$field_key]);
          $query->add_field(null, "(SELECT COUNT(*) FROM {fileusage} fu WHERE fu.externaluser = {users}.uid AND fu.action = 1)", $field_key);
          break;
      }
    }
  }
}

Zauważ, że ponownie wykorzystujemy alias usuniętego pola dla podzapytania. W ten sposób widoki będą myśleć, że wartość zwrócona z podzapytania faktycznie pochodzi z pola zastępczego (które przecież nie istnieje).

To jest. Nie otrzymujemy przyłączenia kartezjańskiego i zarówno „pobieranie”, jak i „słuchanie” są liczone poprawnie.

sbrattla
źródło
4

Używałem rozwiązania sbrattla, dopóki nie musiałem mieć wartości filtru dziedziczącego podzapytania. Teraz używam modułu views_field_view , aby osadzić osobny widok, który wykonuje kwerendę liczenia. Mogę przekazać wartości filtru kontekstowego do tego osadzonego widoku za pośrednictwem modułu views_filterfield (który napisałem), który udostępnia wartości filtrów jako pola widoku (a tym samym tokeny).

Zapytanie zliczające działa teraz i dziedziczy wyeksponowane filtry z głównego zapytania.

Cafuego
źródło