2つのビューの結合を作成する方法は?


36

「投稿日」でソートされたユーザーのノードとコメントの結合を取得しようとしています。この投稿はD6のサンドボックスプロジェクトにリンクしていますが、7には何もありません。

この投稿には、D6でhook_views_pre_execute()とSQL UNIONを使用した例があります。これは、ビュー3のD7では機能しません。

merlinofchaosのコメントに出会いました

Drupalの新しいクエリジェネレーターを使用しているため、クエリはSelectQueryオブジェクトであり、これを変更または置換する必要があります。詳細については、Drupal 7の新しいデータベースレイヤーを参照してください。

誰かがこれを行う方法や2つのビューを組み合わせる他のソリューションの例を持っていますか?


これは実際の答えというよりもアイデアです。ノードとコメントの両方を結合するユーザーに基づいてビューを作成できるはずです(結局、両方とも単にエンティティではありません:)。私の最初の試みでは、ビューはユーザーからコメントへの関係を提供しないため、これを行うことができませんでした。しかし、それは簡単に変更できるはずです。(または、私は何かを忘れました)。
mojzis

以下と同じ答えだと思います:ktには2つのコンテキストフィルターが必要です(content.author =ログインユーザーまたはcomment.author =ログインユーザー)。
-uwe

私はそうは思わない:)私は、ノードとコメントに参加するユーザーに基づいたビューを意味します。しかし、ユーザーとコメントの関係に問題があると感じています-コメントを表示することができませんでした。
mojzis

私は推測していますが、searchapiを使用して複数のエンティティタイプに同時にインデックスを付けることはできませんか?それができたら、両方の部分で使用されるフィールドがあれば、それを使用してそのようなビューを作成できます。
ダニエルウェーナー

1
あるサンドボックスプロジェクトは、Drupalの7のために、確認してください「団結は、ビュー」drupal.org/sandbox/jalama/1785294を
アヌープジョセフ

回答:


15

動作するテスト済みの例を次に示します。

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

  }
}

これはほとんどのビューで機能します。ただし、一部のスタイルプラグインは、この手法では機能しない派手な機能を実行する場合があります(私が見ているカレンダーモジュール)。



2

最終的にdb_query()を使用してSQL UNIONを作成し、theme()関数を使用してページャーを含むテーブルレイアウトにレンダリングしました。

ユーザーにとっては、デフォルトのビューのように見えます。もう1つの利点は、クエリを大幅に最適化できることです。私は「私の友人の活動」を示しています。あなたがそのためにビューを使用する場合、あなたの友人のリストを作成し、50以上または100以上のレコードがある場合は非常に遅いSQL「IN」句で使用します。

その友人のリストを、過去x日間にサイトにログインした人だけに絞り込むことができました。

これはコードサンプルです。

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

将来の参考のために、これは同じテーブルに基づく2つのビューをどのように組み合わせたかです。同じ原則は、同じ量のフィールドを持つ異なるテーブルに基づくビューにも適用する必要があります。

以下の場合、フォーマットがレンダリングされたエンティティに設定されているため、idのみが選択されます。ただし、フィールドを使用する場合は、以下のタイムスタンプを追加したように、フィールドが少ないダミーのフィールドをクエリにいつでも追加できます。

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

私はこれらの線に沿って何かを想像します:

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

私はそれをテストしていませんが。

役立つリンク:

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

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


1
これは完全には機能していないようです。$ view-> queryは、Viewsがクエリを作成するために使用する中間オブジェクトです。SelectQueryは$ view-> build_info ['query']です。それに応じて編集すると、「致命的なエラー:未定義のメソッドSelectQuery :: render_pager()の呼び出し」エラーを超えることはできません。
mpdonadio

1
データベースのテストコードは、組合さの例有しapi.drupal.org/api/drupal/...api.drupal.org/api/drupal/...
mikeytown2


これがおそらく機能する唯一の方法は、両方のビューがほぼまったく同じ場合です。
ダリン

0

Views Field Viewというモジュールに出会いました。これにより、ビューを別のビューのフィールドとして埋め込むことができます。私はまだ自分でこれを試していませんが、あなたに役立つかもしれません。


2
ビューフィールドビューは実際にコメントとノードの両方を取得できますが、フィールド内でのみソートする方法はないと思います。
レサリオン

0

EntityFieldQueryは、バックエンドの景色同時に複数のエンティティタイプのためのサポート問い合わせを。したがって、ノードとコメントの両方を照会するのに使用できるはずです。どちらのエンティティタイプもuidプロパティを使用して作成者にリンクするため、APIレベルでEntityFieldQuery :: propertyCondition()を使用して、単一のユーザーからノードとコメントを選択できます。ビューのバックエンドは同じ機能を提供すると思います。


:彼らはちょうどクエリを複数のエンティティに機能を削除したように見えるdrupal.org/node/1564740
ウーヴェ

0

別のアプローチとして、ノードとコメントのフィードを作成し(URLのユーザー識別子のコンテキストフィルターを使用)、2つのフィードを新しいフィードに結合し、投稿日ごとに表示することもできます。


-2

使用されるグローバル:PHPフィールド?これらを使用して、2つを結合したビューを一緒にテープでダクトできます。

コンテンツ:タイトルおよびコンテンツ:コメントフィールド(表示から除外)でコンテンツのビューを作成します。

どちらがより新しいか、最後に更新された日付、またはユーザーによる最後のコメントの日付を計算するPHPフィールドを追加し、フィールドの値をその日付に設定します。そのフィールドをソート条件として追加します。

コメントまたはノードへのリンクを出力する同様のフィールドを追加します。

私にはいいですね!


面白いアイデア。2つのコンテキストフィルターが必要になります(content.author =ログインユーザーまたはcomment.author =ログインユーザー)。
uwe

これで壮大な回復を期待しています...;)
ジョナサンエルモア

2
このアプローチによるパフォーマンスの低下は恐ろしいことです。実行されるデータベースクエリの潜在的な数は、天文学に寄ることができます。
Rider_X
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.