Comment créer une union de deux vues?

36

J'essaie d'obtenir une union des nœuds et des commentaires d'un utilisateur triés par "date de publication". Cet article est lié aux projets de bac à sable pour D6, mais il n’ya rien pour 7.

Cet article présente un exemple d'utilisation de hook_views_pre_execute () et d'un SQL UNION dans D6. Cela ne fonctionne pas pour D7 avec les vues 3.

Je suis tombé sur le commentaire de Merlinofchaos

Comme nous utilisons maintenant le nouveau générateur de requêtes de Drupal, la requête est un objet SelectQuery que vous devrez modifier ou remplacer. Recherchez la nouvelle couche de base de données Drupal 7 pour plus d'informations.

Quelqu'un at-il un exemple de la façon de procéder ou toute autre solution permettant de combiner deux points de vue?

uwe
la source
c'est plus une idée qu'une vraie réponse: vous devriez pouvoir créer une vue basée sur les utilisateurs, qui joindrait à la fois les nœuds et les commentaires (après tout, ils ne sont que des entités :). Lors de ma première tentative, j’ai omis de le faire car les vues n’offrent pas la relation entre utilisateurs et commentaires. Mais cela devrait être facile à modifier. (ou j'ai juste oublié quelque chose).
mojzis
Je pense que c'est la même réponse que ci-dessous: kt aurait besoin de deux filtres contextuels (content.author = utilisateur connecté OU comment.author = utilisateur connecté).
uwe
Je ne pense pas ainsi :) je veux dire une vue basée sur les utilisateurs, joignant les nœuds et les commentaires. mais j’ai le sentiment qu’il ya un problème avec la relation entre utilisateur et commentaire - je n’ai pas réussi à afficher les commentaires.
mojzis
Je suis en train de deviner, mais vous ne pouvez pas utiliser searchapi pour indexer plusieurs types d'entités en même temps? Une fois que vous avez cela et que vous avez un champ qui est utilisé par les deux parties, vous pouvez l'utiliser pour créer une vue comme celle-ci.
Daniel Wehner
1
Il y a un projet de bac à sable 'Views Unionize' pour drupal 7, veuillez consulter drupal.org/sandbox/jalama/1785294 ,
Anoop Joseph

Réponses:

15

Voici un exemple de travail et testé:

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

  }
}

Cela fonctionne pour la plupart des vues. Cependant, certains plugins de style peuvent faire des choses fantaisistes qui ne fonctionneront pas avec cette technique (module Agenda, je vous regarde).

Dalin
la source
2

J'ai fini par utiliser db_query () pour créer les SQL UNION, puis le rendre dans une présentation de tableau incluant des pagers à l'aide de la fonction theme ().

Pour l'utilisateur, cela ressemble à des vues par défaut. L'autre avantage était que je pouvais optimiser beaucoup la requête. Je montre "les activités de mes amis" et si vous utilisiez des vues pour cela, cela créerait une liste de vos amis et l'utiliserait dans une clause SQL "IN" qui est très lente si vous avez plus de 50 ou 100 enregistrements.

Je pourrais restreindre cette liste d'amis à ceux qui ont été connectés au site au cours des x derniers jours.

Ceci est un exemple de code:

  // 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
la source
1

Pour référence future, voici comment j'ai combiné deux vues basées sur la même table. Les mêmes principes devraient également s'appliquer aux vues basées sur différentes tables avec le même nombre de champs.

Dans le cas ci-dessous, seul id est sélectionné car le format est défini sur entité rendue. Mais si vous utilisez des champs, vous pouvez toujours ajouter des champs factices supplémentaires à la requête comportant moins de champs, comme j'ai ajouté l'horodatage ci-dessous.

/**
 * 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()
    );
  };
}
dur
la source
0

J'imagine que c'est quelque chose comme ça:

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

Bien que je ne l'ai pas testé.

Quelques liens qui peuvent aider:

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

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

cam8001
la source
1
Cela ne semble pas fonctionner pleinement. $ view-> query est l'objet intermédiaire utilisé par Views pour construire la requête. Le SelectQuery est $ view-> build_info ['query']. Lorsque vous modifiez en conséquence, je ne peux pas dépasser l'erreur "Erreur fatale: appel de la méthode non définie SelectQuery :: render_pager ()".
mpdonadio
1
Le code de test de la base de données contient des exemples d'unions api.drupal.org/api/drupal/… et api.drupal.org/api/drupal/…
mikeytown2
un autre exemple drupal.org/node/748844#comment-7070234
mercredi
Cela ne pourrait fonctionner que si les deux vues sont presque identiques.
Dalin
0

Je suis tombé sur un module appelé Vues Field View , qui vous permet d'intégrer une vue en tant que champ dans une autre vue. Je ne l'ai pas encore essayé moi-même, mais cela pourrait vous être utile.

Marijke Luttekes
la source
2
Bien que Vues, ​​Field View puisse en effet recevoir à la fois des commentaires et des nœuds, je ne pense pas qu'il existe un moyen de trier les champs, mais uniquement ceux-ci.
Letharion
0

Le EntityFieldQuery Vues Backend requêtes de support pour plusieurs types d'entités en même temps. Il devrait donc être possible d’interroger les nœuds et les commentaires. Les deux types d'entités utilisent une uidpropriété pour créer un lien avec leur auteur. Par conséquent, au niveau de l'API, EntityFieldQuery :: propertyCondition () devrait être utilisable pour sélectionner les nœuds et les commentaires d'un seul utilisateur. Je suppose que le point de vue offre la même fonctionnalité.

Pierre Buyle
la source
On dirait qu'ils viennent de supprimer la fonctionnalité permettant d'interroger plusieurs entités: drupal.org/node/1564740
lundi
0

Une approche différente pourrait consister à créer des flux de nœuds et de commentaires (avec un filtre contextuel de l'identifiant de l'utilisateur dans l'URL), puis à combiner les deux flux dans un nouveau flux et à l'afficher par date de publication.

Sam Wilson
la source
-2

Utilisé Global: champs PHP ? Vous pouvez les utiliser pour coller ensemble une vue combinant les deux.

Créer une vue de contenu avec contenu: Titre et contenu: Champs de commentaires (exclus de l'affichage).

Ajoutez un champ PHP qui calcule ce qui est le plus récent, la date de la dernière mise à jour ou la date du dernier commentaire de l'utilisateur, et définissez la valeur du champ sur cette date. Ajoutez ce champ comme condition de tri.

Ajoutez un champ similaire qui génère un lien vers le commentaire ou vers le nœud.

Ça me semble bien!

Johnathan Elmore
la source
idée intéressante. Deux filtres contextuels seraient nécessaires (content.author = utilisateur connecté OU comment.author = utilisateur connecté).
mardi
En espérant avoir une récupération épique sur celui-ci ...;)
Johnathan Elmore
2
La performance frappée par cette approche serait effrayante. Le nombre potentiel de requêtes de base de données effectuées pourrait être astronomique.
Rider_X