Как создать союз двух взглядов?

36

Я пытаюсь получить объединение пользовательских узлов и комментариев, отсортированных по «дате публикации». Этот пост ссылается на проекты песочницы для D6, но нет ничего для 7.

В этом посте есть пример использования hook_views_pre_execute () и SQL UNION в D6. Это не работает для D7 с представлениями 3.

Я наткнулся на комментарий merlinofchaos

Поскольку теперь мы используем новый генератор запросов Drupal, запрос представляет собой объект SelectQuery, который вам придется изменить или заменить. Посмотрите новый слой базы данных Drupal 7 для получения дополнительной информации.

У кого-нибудь есть пример того, как сделать это или любое другое решение для объединения двух представлений?

Уве
источник
это скорее идея, чем реальный ответ: вы должны иметь возможность создавать представление, основанное на пользователях, которое будет объединять как узлы, так и комментарии (в конце концов, они оба не просто сущности :). С моей первой попытки мне не удалось сделать это, потому что представления не предлагают отношения от пользователя к комментарию. Но это должно быть легко изменить. (или я просто что-то забыл).
Мойзис
Я думаю, что это тот же ответ, что и ниже: для kt потребуются два контекстных фильтра (content.author = пользователь, вошедший в систему, ИЛИ comment.author = пользователь, вошедший в систему).
Uwe
я так не думаю :) я имею в виду представление, основанное на пользователях, соединяющих узлы и комментарии. но у меня есть ощущение, что есть некоторая проблема с отношением между пользователем и комментарием - мне не удалось показать комментарии.
Мойзис
Я просто догадываюсь, но разве вы не можете использовать searchapi для одновременного индексирования нескольких типов сущностей? Если у вас есть это и у вас есть поле, которое используется обеими частями, вы можете использовать его для создания такого представления.
Даниэль Венер
1
Для drupal 7 существует проект песочницы «Views Unionize», пожалуйста, проверьте 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());

  }
}

Это работает для большинства просмотров. Однако некоторые плагины стиля могут делать причудливые вещи, которые не будут работать с этой техникой (модуль календаря, который я смотрю на вас).

Далин
источник
3

Вы можете использовать модуль дополнительных обработчиков Views для генерации запросов SQL UNION из двух разных представлений / дисплеев.

Подробное руководство на drupal.org здесь

https://www.drupal.org/project/views_extra_handlers скриншот просмотров изменить настройки

TechNikh
источник
2

В итоге я использовал db_query () для создания SQL UNION, а затем преобразовал его в макет таблицы, включая пейджеры, используя функцию theme ().

Для пользователя это выглядит как вид по умолчанию. Другое преимущество состояло в том, что я мог много оптимизировать запрос. Я показываю «действия моего друга», и если бы вы использовали для этого представления, он создал бы список ваших друзей и использовал бы его в предложении SQL «IN», что очень медленно, если у вас более 50 или 100 записей.

Я мог бы сузить этот список друзей только до тех, кто зашел на сайт за последние 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

Для дальнейшего использования, вот как я объединил два представления на основе одной таблицы. Те же принципы должны применяться к представлениям, основанным на разных таблицах с одинаковым количеством полей.

В нижеследующем случае выбирается только идентификатор, так как формат установлен для визуализируемого объекта. Но если вы работаете с полями, вы всегда можете добавить дополнительные фиктивные поля в запрос, который имеет меньше полей, как я добавил временную метку ниже.

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

cam8001
источник
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
13
Единственный способ, которым это может сработать, - это если оба представления почти одинаковы.
Далин
0

Я натолкнулся на модуль с именем View Field View , который позволяет вам встраивать вид как поле в другой вид. Я еще не пробовал это сам, но это может быть полезно для вас.

Марийке Люттекес
источник
2
Несмотря на то, что View Field View действительно может получать как комментарии, так и узлы, я не верю, что есть способ сортировки по полям, только внутри них.
Летарион
0

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

Пьер Буйль
источник
похоже, что они только что удалили эту функцию для запроса нескольких сущностей: drupal.org/node/1564740
uwe
0

Другой подход может заключаться в создании каналов узлов и комментариев (с контекстным фильтром идентификатора пользователя в URL-адресе), а затем объединить два канала в новый канал и отобразить его по дате публикации.

Сэм Уилсон
источник
-2

Используется Global: поля PHP ? Вы можете использовать их, чтобы соединить клейкой лентой вид, который объединяет их.

Создайте представление содержимого с полями Content: Title и Content: Comments (исключено из отображения).

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

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

Это звучит хорошо для меня!

Джонатан Элмор
источник
интересная идея. Для этого потребуются два контекстных фильтра (content.author = пользователь вошел в систему ИЛИ comment.author = пользователь вошел в систему).
Uwe
Надеемся получить эпическое выздоровление на этом ...;)
Джонатан Элмор
2
Падение производительности при таком подходе было бы страшным. Потенциальное число выполненных запросов к базе данных может оказаться астрономическим.
Rider_X