¿Cómo crear una unión de dos puntos de vista?

36

Estoy tratando de obtener una unión de los nodos y comentarios de un usuario ordenados por "fecha de publicación". Esta publicación enlaza con proyectos de sandbox para D6 pero no hay nada para 7.

Esta publicación tiene un ejemplo del uso de hook_views_pre_execute () y un SQL UNION en D6. Esto no funciona para D7 con vistas 3.

Me encontré con el comentario de Merlinofchaos

Como ahora estamos utilizando el nuevo generador de consultas de Drupal, la consulta es un objeto SelectQuery que deberá modificar o reemplazar. Consulte la nueva capa de base de datos de Drupal 7 para obtener más información.

¿Alguien tiene un ejemplo de cómo hacer esto o cualquier otra solución para combinar dos puntos de vista?

uwe
fuente
esta es más una idea que una respuesta real: debería poder crear una vista basada en los usuarios, que uniría tanto los nodos como los comentarios (después de todo, no son solo entidades :). En mi primer intento, no pude hacer esto porque las vistas no ofrecen la relación del usuario con el comentario. Pero eso debería ser fácil de alterar. (O acabo de olvidar algo).
mojzis
Creo que es la misma respuesta que a continuación: kt requeriría dos filtros contextuales (content.author = usuario registrado O comment.author = usuario registrado).
Uwe
no lo creo :) me refiero a una vista basada en usuarios, uniendo los nodos y comentarios. pero tengo la sensación de que hay algún problema con la relación entre usuario y comentario; no pude mostrar los comentarios.
mojzis
Solo estoy adivinando, pero ¿no puedes usar searchapi para indexar múltiples tipos de entidades al mismo tiempo? Una vez que tenga eso y tenga un campo que es usado por ambas partes, puede usarlo para construir una vista como esa.
Daniel Wehner
1
Hay un proyecto de sandbox 'Views Unionize' para drupal 7, consulte drupal.org/sandbox/jalama/1785294 ,
Anoop Joseph

Respuestas:

15

Aquí hay un ejemplo funcional y probado:

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

  }
}

Esto funciona para la mayoría de las vistas. Sin embargo, algunos complementos de estilo pueden hacer cosas sofisticadas que no funcionarán con esta técnica (módulo de calendario que te estoy mirando).

Dalin
fuente
2

Terminé usando db_query () para crear las UNIONES SQL y luego representarlo en un diseño de tabla que incluye localizadores que usan la función theme ().

Para el usuario, parece vistas predeterminadas. El otro beneficio fue que pude optimizar mucho la consulta. Estoy mostrando "las actividades de mis amigos" y si usaras vistas para eso, crearía una lista de tus amigos y la usaría en una cláusula SQL "IN" que es muy lenta si tienes más de 50 o 100 registros.

Podría limitar esa lista de amigos solo a los que han iniciado sesión en el sitio en los últimos x días.

Este es un ejemplo de código:

  // 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();
uwe
fuente
1

Para referencia futura, así es como combiné dos vistas basándose en la misma tabla. Los mismos principios también deberían aplicarse a las vistas basadas en diferentes tablas con la misma cantidad de campos.

En el siguiente caso, solo se selecciona id, ya que el formato se establece en la entidad representada. Pero si va con campos, siempre puede agregar campos ficticios adicionales a la consulta que tiene menos campos como agregué la marca de tiempo a continuación.

/**
 * 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()
    );
  };
}
duru
fuente
0

Me imagino que es algo así:

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

Aunque no lo he probado.

Algunos enlaces que pueden ayudar:

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

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

cam8001
fuente
1
Esto no parece funcionar completamente. $ view-> query es el objeto intermedio que Views usa para construir la consulta. SelectQuery es $ view-> build_info ['query']. Cuando edita en consecuencia, no puedo superar un error de "Error grave: llamada al método indefinido SelectQuery :: render_pager ()".
mpdonadio
1
El código de prueba de la base de datos tiene ejemplos de sindicatos api.drupal.org/api/drupal/… y api.drupal.org/api/drupal/…
mikeytown2
La única forma en que esto podría funcionar es si ambas vistas son casi exactamente iguales.
Dalin
0

Encontré un módulo llamado Vista de campo de vistas , que le permite incrustar una vista como campo en otra vista. Todavía no lo he probado todavía, pero podría ser útil para usted.

Marijke Luttekes
fuente
2
Si bien Vistas de campo puede obtener comentarios y nodos, no creo que haya una forma de clasificar los campos, solo dentro de ellos.
Letharion
0

El backend de EntityFieldQuery Views admite consultas para múltiples tipos de entidades al mismo tiempo. Por lo tanto, debería ser utilizable para consultar tanto los nodos como los comentarios. Ambos tipos de entidad usan una uidpropiedad para vincular a su autor, por lo que a nivel de API EntityFieldQuery :: propertyCondition () debería poder usarse para seleccionar los nodos y comentarios de un solo usuario. Supongo que el backend de las vistas ofrece la misma característica.

Pierre Buyle
fuente
parece que acaban de eliminar la función para consultar varias entidades: drupal.org/node/1564740
uwe
0

Un enfoque diferente podría ser crear fuentes de nodos y comentarios (con un filtro contextual del identificador del usuario en la URL) y luego combinar las dos fuentes en una nueva fuente, y mostrar esto por fecha de publicación.

Sam Wilson
fuente
-2

Global usado : PHP campos ? Puede usarlos para unir con cinta adhesiva una Vista que combine los dos.

Cree una vista de contenido con los campos Contenido: Título y Contenido: Comentarios (Excluido de la pantalla).

Agregue un campo PHP que calcule cuál es más reciente, la fecha de la última actualización o la fecha del último comentario del usuario, y configure el valor del campo para que sea esa fecha. Agregue ese campo como una condición de clasificación.

Agregue un campo similar que genere un enlace al comentario o al nodo.

¡Suena bien para mi!

Johnathan Elmore
fuente
idea interesante. Requeriría dos filtros contextuales (content.author = usuario registrado O comment.author = usuario registrado).
Uwe
Esperando obtener la recuperación épica en este ...;)
Johnathan Elmore
2
El rendimiento de este enfoque sería aterrador. El número potencial de consultas a la base de datos realizadas podría ser astronómico.
Rider_X