Como criar uma união de duas visões?


36

Estou tentando obter uma união dos nós e comentários de um usuário classificados por "data de postagem". Esta postagem tem links para projetos de sandbox para o D6, mas não há nada para o 7.

Este post tem um exemplo do uso de hook_views_pre_execute () e um SQL UNION no D6. Isso não funciona para o D7 com visualizações 3.

Me deparei com o comentário de merlinofchaos

Como agora estamos usando o novo gerador de consultas do Drupal, a consulta é um objeto SelectQuery que você precisará modificar ou substituir. Consulte a nova camada de banco de dados do Drupal 7 para obter mais informações.

Alguém tem um exemplo de como fazer isso ou qualquer outra solução para combinar duas visualizações?


isso é mais uma ideia do que uma resposta real: você deve ser capaz de criar uma visão baseada nos usuários, que uniria os nós e os comentários (eles não são apenas entidades afinal de contas :). Na minha primeira tentativa, não consegui fazer isso porque as visualizações não oferecem a relação do usuário para comentar. Mas isso deve ser fácil de alterar. (ou eu esqueci alguma coisa).
Mojzis

Eu acho que é a mesma resposta que abaixo: o kt exigiria dois filtros contextuais (content.author = usuário logado OU comment.author = usuário logado).
uwe 23/05

acho que não :) quero dizer uma visão baseada em usuários, juntando os nós e comentários. mas tenho a sensação de que há algum problema com a relação entre usuário e comentário - não consegui mostrar os comentários.
Mojzis

Estou apenas adivinhando, mas você não pode usar searchapi para indexar vários tipos de entidade ao mesmo tempo? Depois de ter isso e ter um campo que é usado pelas duas partes, você pode usá-lo para criar uma visualização como essa.
Daniel Wehner

1
Existe um projeto de sandbox 'Views Unionize' para o drupal 7, verifique drupal.org/sandbox/jalama/1785294 ,
Anoop Joseph 26/12

Respostas:


15

Aqui está um exemplo de trabalho e testado:

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

  }
}

Isso funciona para a maioria das visualizações. No entanto, alguns plugins de estilo podem fazer coisas sofisticadas que não funcionam com essa técnica (módulo Calendário, estou olhando para você).



2

Acabei usando db_query () para criar os UNIONs SQL e, em seguida, renderizando-os em um layout de tabela, incluindo pagers usando a função theme ().

Para o usuário, ele se parece com as visualizações padrão. O outro benefício foi que eu pude otimizar bastante a consulta. Estou mostrando "atividades do meu amigo" e, se você usasse modos de exibição para isso, criaria uma lista de seus amigos e a usaria na cláusula SQL "IN", que é muito lenta se você tiver mais de 50 ou 100 registros.

Eu poderia restringir essa lista de amigos apenas àqueles que foram conectados ao site nos últimos x dias.

Este é um exemplo 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();

1

Para referência futura, é assim que eu combinei duas visualizações com base na mesma tabela. Os mesmos princípios também devem ser aplicados em visualizações baseadas em tabelas diferentes com a mesma quantidade de campos.

No caso abaixo, apenas o ID é selecionado, pois o formato está definido como entidade renderizada. Mas se você optar por campos, sempre poderá adicionar campos fictícios adicionais à consulta que possui menos campos, como adicionei o carimbo de data / hora abaixo.

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

Eu imagino que é algo nesse sentido:

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

Embora eu não tenha testado.

Alguns links que podem ajudar:

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

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


1
Isso não parece funcionar totalmente. $ view-> query é o objeto intermediário que o Views usa para criar a consulta. O SelectQuery é $ view-> build_info ['query']. Quando você edita de acordo, não consigo ir além do erro "Erro fatal: chame o método indefinido SelectQuery :: render_pager ()".
mpdonadio

1
O código de teste de banco de dados tem exemplos de sindicatos api.drupal.org/api/drupal/... e api.drupal.org/api/drupal/...
mikeytown2


A única maneira de isso funcionar é se as duas visualizações forem quase exatamente iguais.
Dalin 30/10/2013

0

Me deparei com um módulo chamado Views Field View , que permite incorporar uma view como um campo em outra view. Ainda não testei isso ainda, mas pode ser útil para você.


2
Embora o Views Field View possa de fato receber comentários e nós, não acredito que haja uma maneira de classificar os campos, apenas dentro deles.
Letharion

0

O back-end EntityFieldQuery Views suporta a consulta de vários tipos de entidade ao mesmo tempo. Portanto, deve ser utilizável consultar nós e comentários. Os dois tipos de entidade usam uma uidpropriedade para vincular seu autor, portanto, no nível da API, EntityFieldQuery :: propertyCondition () deve ser utilizável para selecionar os nós e comentários de um único usuário. Eu acho que as visualizações de back-end oferecem o mesmo recurso.


Parece que acabou de remover o recurso para consultar várias entidades: drupal.org/node/1564740
Uwe

0

Uma abordagem diferente poderia ser criar feeds de nós e comentários (com um filtro contextual do identificador do usuário no URL) e depois combinar os dois feeds em um novo feed e exibi-lo por data de postagem.


-2

Global: campos PHP usados ? Você pode usá-los para unir uma vista que combina os dois.

Crie uma exibição do conteúdo com os campos Conteúdo: Título e Conteúdo: Comentários (excluídos da exibição).

Adicione um campo PHP que calcule qual é mais recente, a data da última atualização ou a data do último comentário do usuário e defina o valor do campo para essa data. Adicione esse campo como uma condição de classificação.

Adicione um campo semelhante que produz um link para o comentário ou para o nó.

Parece bom para mim!


ideia interessante. Seria necessário dois filtros contextuais (content.author = usuário conectado OU comment.author = usuário conectado).
uwe 23/05

Na esperança de obter a recuperação épica em um presente ...;)
Johnathan Elmore

2
O desempenho atingido por essa abordagem seria assustador. O número potencial de consultas ao banco de dados executadas poderia abordar astronômicas.
Rider_X
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.