Change record status: 
Project: 
Introduced in branch: 
8.x
Description: 

As of Drupal 8 drupal_goto() has been removed in favor of RedirectResponse which comes together with the Symfony HttpFoundation.

hook_drupal_goto_alter() was also removed as well, in favor of just using an event listener on kernel.response

Redirecting

Drupal 7

<?php
function my_menu_callback_foo() {
  //....
  drupal_goto('user');
}
?>

Drupal 8 (procedural)

<?php
use Symfony\Component\HttpFoundation\RedirectResponse;

function my_menu_callback_foo() {
  //....
  return new RedirectResponse(\Drupal::url('user.page'));
}
?>

Drupal 8 (properly injected)

<?php
use Drupal\Core\Controller\ControllerBase;

class MyControllerClass extends ControllerBase {

  public function foo() {
    //...
    return $this->redirect('user.page');
  }
}
?>

If the route name is not known or it is external:

<?php
use Drupal\Core\Controller\ControllerBase;

class MyControllerClass extends ControllerBase {

  public function foo() {
    //...
    return new RedirectResponse('https://example.com/some/path'); // for eg. Url::fromUserInput(\Drupal::destination()->get())->setAbsolute()->toString();
  }
}
?>

Note: #2023445: Improve DX of doing a redirect might change the way this is handled.

Altering the redirection URL:

D7

<?php
/**
 * Implements hook_drupal_goto_alter().
 */
function mymodule_drupal_goto_alter(&$path, &$options, &$http_response_code) {
  if  ($path == 'http://example.com') {
     $path = 'http://example2.com';
  }
}
?>

D8
in mymodule.services.yml:

services:
  mymodule.subscriber:
    class: Drupal\mymodule\EventSubscriber\MyModuleSubscriber
    tags:
      - { name: event_subscriber }

<?php
namespace Drupal\mymodule\EventSubscriber;

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

class MyModuleSubscriber implements EventSubscriberInterface {

  public function checkRedirection(FilterResponseEvent $event) {
    $response = $event->getResponse();
    if ($response instanceOf RedirectResponse && $response->getTargetUrl() == 'http://example.com') {
       $response->setTargetUrl('http://example2.com');
    }
  }

  static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = array('checkRedirection');
    return $events;
  }
}
?>

Redirecting to the same page

You should avoid doing this dynamic lookup and specify the route you wish to redirect to.
Note that all usages of this in core were replaced by specific redirects.
Drupal 7

<?php
function my_menu_callback_foo() {
  //....
  drupal_goto();
}
?>

Drupal 8 (procedural)

<?php
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Routing\RouteMatch;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;

class MyControllerClass extends ControllerBase {

  public function foo(Request $request) {
    $route_match = $route = RouteMatch::createFromRequest($request);
    //...
    return $this->redirect($route_match->getRouteName(), $route_match->getRawParameters()->all());
  }
}
?>

Redirecting to the home page

Drupal 7

<?php
function my_menu_callback_foo() {
  //....
  drupal_goto('');
}
?>

Drupal 8 (procedural)

<?php
use Drupal\Core\Controller\ControllerBase;

class MyControllerClass extends ControllerBase {

  public function foo(Request $request) {
    //...
    return $this->redirect('<front>');
  }
}
?>
Impacts: 
Module developers
Updates Done (doc team, etc.)
Online documentation: 
Not done
Theming guide: 
Not done
Module developer documentation: 
Not done
Examples project: 
Not done
Coder Review: 
Not done
Coder Upgrade: 
Not done
Other: 
Other updates done

Comments

mudassar774’s picture

I am trying to redirect from event subscriber but got error ERR_TOO_MANY_REDIRECT below is my code can anyone help me.

public static function getSubscribedEvents() {
$events[KernelEvents::RESPONSE][] = array('checkSessionLimit');
return $events;
}


public function checkSessionLimit(FilterResponseEvent $event){


$event->setResponse($this->redirect('session.limit'));
}
gngn’s picture

I tried to redirect in a hook_form_alter().
Looking for a solution I found quite a few questions about redirecting in D8 but none of the solutions worked for me - until i found http://drupal.stackexchange.com/questions/138697/how-we-replace-goto-wit...

Problem seems to be redirecting inside a hook_form_alter()... (?)

Anyway, this worked for me:

<?php
function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  // ...
  $response = new RedirectResponse('/non-member-registration');
  $response->send();
}
?>
johnvb’s picture

Under Drupal 7, I could do something like:

<?php
drupal_set_message('You have been redirected because...');
drupal_goto($url);
?>

Under Drupal 8, if I do the following then the message is not displayed:

<?php
drupal_set_message('You have been redirected because...');
$response = new RedirectResponse(hostsite_get_url($path, $params));
$response->send();
?>

After investigation I've found that this is because RedirectResponse does not terminate the current script unlike drupal_goto, so the page is still rendered and messages get output but then immediately lost. A quick fix for this is to insert a call to exit() after sending the response.

<?php
drupal_set_message('You have been redirected because...');
$response = new RedirectResponse(hostsite_get_url($path, $params));
$response->send();
exit();
?>