0

Views page show content. How to redirect to content page if views has only one result?

1

In your theme's themename.theme file add:

At the very top add:

use Drupal\views\ViewExecutable;
use Symfony\Component\HttpFoundation\RedirectResponse;

Then add:

/*
 * Implements hook_views_pre_render()
 */
function THEMENAME_views_pre_render(ViewExecutable $view) {
    if($view->id() == "view_name" && $view->current_display == 'view_machine_name') {
      if (!empty($view->result) && count($view->result) == 1) {
        $url = $view->result[0]->_entity->toUrl()->toString();
        $response = new RedirectResponse($url);
        $response->send();
      }
    }
}

Clear the cache so changes kick in.


my_module/src/Controller/ViewPageController.php

namespace Drupal\my_module\Controller;

use Drupal\Core\Cache\CacheableRedirectResponse;
use Drupal\Core\Controller\ControllerBase;
use Drupal\views\Views;

/**
 * Defines HelloController class.
 */
class ViewPageController extends ControllerBase {

  public function content() {

    $view = Views::getView('view_name');
    $view->setDisplay('view_machine_name');
    $view->execute();

    if (!empty($view->result) && count($view->result) == 1) {

      $url = $view->result[0]->_entity->toUrl()->toString(TRUE);
      $response = new CacheableRedirectResponse($url->getGeneratedUrl());
      $response->getCacheableMetadata()->addCacheTags($view->getCacheTags());
      $response->addCacheableDependency($url);
      return $response;

    }
    else {

      return [
        '#type' => 'view',
        '#name' => 'view_name',
        '#view' => $view,
        '#display_id' => 'view_machine_name',
        '#embed' => TRUE,
        '#cache' => $view->getCacheTags(),
      ];

    }

  }

}

This is the view_machine_name.

  • 1
    You need to clear the cache every time ;-). It's never a good idea to send a response instead of returning it. But for this use case when a redirect depends on database content I think a custom controller which either returns the view or a cacheable redirect response containing the correct cache metadata would be the best approach. – 4k4 May 16 at 8:57
  • @4k4 You need to clear the cache every time Doesn't the view get invalidated via cache tag? Or are you referring to when adding a new hook? – No Sssweat May 16 at 9:06
  • 1
    Yes, but the redirect needs to get invalidated, too, when the view result is no longer 1. The problem with sending is you have to responses, one you've sent and one which is getting cached, which makes this quite unpredictable what happens. – 4k4 May 16 at 9:11
  • @4k4 you're right, I could've sworn it worked for me without having to clear the cache, but now it won't work unless I clear the cache. Oh I see now, I prob got a false positive due to having multiple view blocks on the page. I didn't do a view_name conditional. – No Sssweat May 16 at 9:32
  • 1
    No, $response->addCacheableDependency($url); doesn't work when this is already applied. – 4k4 May 16 at 12:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.