1

I have a site where I set a cookie when the user is visiting a specific content-type:

function THEME_preprocess_node(&$variables) {
  if (isset($variables['node']) && $variables['node']->getType() == 'MYTYPE') {
    // Store cookie with id of active node.
    user_cookie_save(['THEME_location' => $variables['node']->get('nid')->getString()]);
  }
}

Then if the user again is going to the frontpage, I would like to redirect him to the node referenced from the above cookie:

function THEME_preprocess(&$variables, $hook) {
  $variables['is_front'] = \Drupal::service('path.matcher')->isFrontPage();

  // Redirect the user to the selected node.
  $cookies = \Drupal::request()->cookies->all();
  if ($variables['is_front'] && isset($cookies['Drupal_visitor_THEME_location'])) {
    $nid = $cookies['Drupal_visitor_THEME_location'];
    $response = new RedirectResponse(\Drupal::url('entity.node.canonical', ['node' => $nid]));
    $response->send();
  }
}

The above works fine most of the time, but sometimes when loggin out from the backend and visiting the frontpage I only get a white screen and the page is completly dead. I know this is very vague but I cannot seem to reproduce this error by performing some specific steps. It just happens once in a while. If I then clear the cache everything seems to work as expected again? Can someone see what I am doing wrong here?

4
  • 3
    You should not use theme_preprocess to do any "live" action, only to alter the variables in a way that can be cached. Your preprocess causes the cached response to be empty, hence the WSOD/ Commented Aug 11, 2017 at 9:49
  • @AlfredArmstrong - Hm, okej. So, what you are saying is that I should move the cookie handling into a module right? And then use which hooks to accomplish the same? Commented Aug 11, 2017 at 9:50
  • 2
    This page explains one way to do it using an event subscriber: drupal.org/node/2013014 or you could use hook_page_alter I think. Commented Aug 11, 2017 at 9:54
  • @AlfredArmstrong - I succesfully added an event subscriber. Add an answer and I will accept it. Commented Aug 12, 2017 at 15:10

1 Answer 1

3

You should not be using theme_preprocess to perform any processing the results of which cannot be cached, only manipulation of variables to be passed to the final theme processing function or template.

Doing a redirection in a theme_preprocess will cause the result to be empty and this is what leads to the WSOD, I believe.

Instead the preferred method is to use an event subscriber, as described on this page: https://www.drupal.org/node/2013014

Register your Event Subscriber in your mymodule.services.yml and tag it as such:

services:
  mymodule_event_subscriber:
    class: Drupal\mymodule\EventSubscriber\MymoduleSubscriber
    tags:
      - {name: event_subscriber}

Your MymoduleSubscriber should be placed in folder structure of modules/src/EventSubscriber/MymoduleSubscriber.php and should implement the EventSubscriberInterface interface and in its getSubscribedEvents() point to the method that should be executed:

namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MymoduleSubscriber implements EventSubscriberInterface {

  public function checkForRedirection(GetResponseEvent $event) {
    if ($event->getRequest()->query->get('redirect-me')) {
      $event->setResponse(new RedirectResponse('http://example.com/'));
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkForRedirection');
    return $events;
  }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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