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?

有帮助吗?

解决方案

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;
  }

}
许可以下: CC-BY-SA归因
scroll top