Generating URLs and Redirects in Drupal 8

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.