Generating URLs and Redirects in Drupal 8

February 22, 2016
Screenshot of

When creating various pages developers often have to generate links, URLs and occasionally redirect users to where they came from, or any other arbitrary page. In Drupal 7 we used l(), drupal_get_destination() and drupal_goto(). As you may suspect, things have changed drastically with Drupal 8. Although drupal_get_destination() is still there, it is marked deprecated, so we should not be using it any longer.

URL generation

When adding a URL into a string, for instance in a text description, core recommends we use the \Drupal\Core\Url class. This has a few handy methods:

  • Internal URL based on a route - Url::fromRoute(), Example: Url::fromRoute('acquia_connector.settings')
  • Internal URL based on a path - Url::fromInternalUri(), Example: Url::fromInternalUri('node/add')
  • External URL - Url::fromUri, Example: Url::fromUri('')

The last two methods are very similar, the main difference is, that fromInternalUri() already assumes an 'internal:' prefix, which tells Drupal to build an internal path. It's worth reading up on what prefixes are supported, for instance the ':entity' prefix can help in building dynamic URIs.

When you need to constrict and display the link as text you can use the toString() method: Url::fromRoute('acquia_connector.settings')->toString().

Redirection - drupal_goto in Drupal 8

Back in the days, things were simple. The bread was cheaper, Drupal was procedural and developers were using drupal_goto(), like there is no tomorrow. But times are changing. Drupal is now object-oriented, and response generation became more regulated than before.

To redirect the visitor, one typically placed drupal_goto()s into his, or her page callback. Page callbacks are a thing of the past now, being replaced by Controllers. A typical route will respond with a Controller class which extends ControllerBase, and is responsible for delivering the right response to the browser. To issue a redirection, we simply need to return the right response. Under the hood this is handled via the RedirectResponse class, courtesy of Symfony:

use Drupal\Core\Url; ... return new RedirectResponse(Url::fromUri('/node/add'));

The ControllerBase class in Drupal 8 (via the UrlGeneratorTrait trait) exposes the redirect() method, which gives us a handy shortcut, so in case you are redirecting to an internal route, you can implement the same redirection by simply calling: return $this->redirect('acquia_connector.settings');.

Summary - tl;dr

  • l() is gone. Use \Drupal\Core\Link for full link objects, and \Drupal\Core\Url for URL generation.
  • drupal_goto() is gone. Use a RedirectResponse, or the redirect() method in your controller.

Sign-up for our Developer Blog Newsletter


Add comment


For Drupal 8.1.8, just returning the new RedirectResponse, don't works. I need to force the response to send the data(headers), and then return. Like this:

$response = new RedirectResponse($url->toString());

Also, note this is on the .theme file, not in a custom module.

Here's the import the readers should magically know:
use Symfony\Component\HttpFoundation\RedirectResponse;