Як створити союз двох поглядів?


36

Я намагаюся отримати об'єднання вузлів та коментарів користувача, відсортованих за "датою публікації". Цей пост посилається на пісочні проекти для D6, але немає нічого для 7.

У цій публікації є приклад використання гачки_все_предупреждение () та SQL UNION у D6. Це не працює для D7 із переглядами 3.

Я натрапив на меринофчаос ' коментар

Оскільки зараз ми використовуємо новий генератор запитів Drupal, запит є об'єктом SelectQuery, який вам доведеться змінювати або замінювати. Шукайте новий рівень баз даних Drupal 7 для отримання додаткової інформації.

Хтось має приклад, як зробити це чи будь-яке інше рішення для поєднання двох поглядів?


це скоріше ідея, ніж реальна відповідь: ви повинні мати можливість створити представлення на основі користувачів, які приєдналися б як до вузлів, так і до коментарів (хіба вони обидва просто сутності :). З моєї першої спроби мені цього не вдалося, оскільки представлення не пропонують відношення від користувача до коментаря. Але це має бути легко змінити. (або я просто щось забув).
mojzis

Я думаю, що це та сама відповідь, що наведена нижче: kt потребує двох контекстних фільтрів (content.author = увійшов в систему або АБО comment.author = увійшов користувач).
uwe

Я не думаю, що так :) Я маю на увазі думку, засновану на користувачах, що приєднуються до вузлів та коментарів. але у мене є відчуття, що є певна проблема у відносинах між користувачем та коментарем - мені не вдалося показати коментарі.
mojzis

Я просто здогадуюсь, але ви не можете використовувати searchchapi, щоб одночасно індексувати кілька типів сутності? Як тільки у вас є і у вас є поле, яке використовується обома частинами, ви можете використовувати це для створення подібного виду.
Даніель Венер

1
Є проект пісочниці "Перегляди Unionize" для drupal 7, будь ласка, перевір Drupal.org/sandbox/jalama/1785294 ,
Anoop Joseph

Відповіді:


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, а потім перетворював його в макет таблиці, включаючи пейджери, використовуючи функцію тема ().

Для користувача це виглядає як перегляди за замовчуванням. Іншою перевагою було те, що я міг багато оптимізувати запит. Я показую "діяльність мого друга", і якщо ви використовуватимете погляди для цього, це створить список ваших друзів і використає його в пункті "IN" SQL, яке дуже повільно, якщо у вас є більше 50 або 100 записів.

Я міг би звузити цей список друзів лише тим, хто був увійшов на сайт за останні х днів.

Це зразок коду:

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

Для подальшого ознайомлення, саме так я поєднав два погляди на основі однієї таблиці разом. Ті ж принципи повинні застосовуватися і до представлень, заснованих на різних таблицях з однаковою кількістю полів.

У нижньому випадку вибирається лише ідентифікатор, оскільки формат встановлений для відображеної сутності. Але якщо ви збираєтесь із полями, ви завжди можете додати додаткові манекенні поля до запиту, у яких менше полів, як я додав часову позначку нижче.

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

Ще один приклад drupal.org/node/748844#comment-7070234
Uwe

Єдиний спосіб цього може працювати, якщо обидва погляди майже однакові.
Далін

0

Я натрапив на модуль під назвою Views Field View , який дозволяє вбудовувати подання як поле в інший вигляд. Я ще цього не пробував, але це може бути корисним для вас.


2
Хоча View Field Field View дійсно може отримувати як коментарі, так і вузли, я не вірю, що існує спосіб сортування полів лише в них.
Летаріон

0

EntityFieldQuery Views Backend підтримки запитів для декількох типів об'єктів одночасно. Тому слід використовувати запити як для вузлів, так і для коментарів. Обидва типи об'єктів використовують uidвластивість для зв’язку зі своїм автором, тому на рівні API EntityFieldQuery :: propertyCondition () має бути доступним для вибору вузлів та коментарів одного користувача. Я думаю, що бекенд перегляду надає ту саму функцію.


Схоже , вони просто прибрали функцію запиту декількох об'єктів: drupal.org/node/1564740
Уве

0

Інший підхід може полягати у створенні каналів вузлів та коментарів (з контекстним фільтром ідентифікатора користувача в URL-адресі), а потім об'єднати два канали в новий канал і відобразити це за датою публікації.


-2

Б / в Global: PHP поля? Ви можете використовувати їх для з'єднання стрічки разом Вид, який поєднує два.

Створіть перегляд вмісту за допомогою вмісту: заголовки та вміст: поля коментарів (виключається з відображення).

Додайте поле PHP, яке обчислює, чи є останні, дату останнього оновлення або дату останнього коментаря користувачем, і встановіть значення поля для цієї дати. Додайте це поле як умову сортування.

Додайте аналогічне поле, яке виводить або посилання на коментар, або на вузол.

Це мені добре звучить!


цікава ідея. Для цього знадобляться два контекстні фільтри (content.author = увійшов в систему або АБО comment.author = увійшов користувач).
uwe

Сподіваючись отримати епічне відновлення на цьому ...;)
Джоннатан Елмор

2
Результат цього підходу був би жахливим. Потенційна кількість запитів до бази даних, що виконується, може поширитись на астрономічні.
Rider_X
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.