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


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

  }
}

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



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


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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.