61

My site is on http://drupal8.local/. How do I get the drupal8.local part of that URL?

Url::fromRoute('<'current'>') or base_path() returns the path parth of the URL; For example, for http://drupal8.local/a/b/c/d/e/f, they return '/a/b/c/d/e/f' when I just need to get 'drupal8.local'.

How can I get that part of the URL?

1
  • 2
    Do you actually mean hostname or base URL? The base URL can include path portions when Drupal isn't run in the root directory.
    – mpdonadio
    Jun 1, 2016 at 15:25

7 Answers 7

114

You can get the hostname, "drupal8.local", directly from the getHost() request:

$host = \Drupal::request()->getHost();

In some cases you might want to get the schema as well, fx https://drupal8.local:

$host = \Drupal::request()->getSchemeAndHttpHost();
10
  • 39
    Note: \Drupal::request()->getSchemeAndHttpHost() will return http://drupal8.local.
    – Tim
    Nov 22, 2016 at 14:54
  • 20
    Note if your site is on a subpath (e.g. your homepage is on drupal8.local/uk), this will not return the subpath. To do this you can use Url::fromRoute('<front>', [], ['absolute' => TRUE]);
    – leon.nk
    Oct 5, 2017 at 12:42
  • 3
    Upvoting comments from leon.nk. Url is going to get you the sub directory and any port if you are on a non-standard port. And, Url is replaced by urlGenerator. Updated code is: \Drupal::urlGenerator()->generateFromRoute('<front>', [], ['absolute' => TRUE]); May 9, 2018 at 16:02
  • 2
    Running this from Drush (version 8) this will give a result : Default.
    – Justme
    May 28, 2018 at 12:07
  • 1
    Correct @Justme - drush is a command line tool so naturally there’s no http host
    – Clive
    May 28, 2018 at 13:14
10

There are some warnings about directly accessing the request object in this way in \Drupal::request:

 * Note: The use of this wrapper in particular is especially discouraged. Most
 * code should not need to access the request directly.  Doing so means it
 * will only function when handling an HTTP request, and will require special
 * modification or wrapping when run from a command line tool, from certain
 * queue processors, or from automated tests.
 *
 * If code must access the request, it is considerably better to register
 * an object with the Service Container and give it a setRequest() method
 * that is configured to run when the service is created.  That way, the
 * correct request object can always be provided by the container and the
 * service can still be unit tested.

Any form controller extending \Drupal\Core\Form\FormBase automatically has this dependency injected, and it may be accessed using:

$this->getRequest()->getSchemeAndHttpHost()

I think (but haven't tested) that a regular page controller extending \Drupal\Core\Controller\ControllerBase could provide the request_stack service by overriding the \Drupal\Core\Controller\ControllerBase::create function, and then setting a $request property in the constructor. This is described really well for forms, and the same process should apply for page controllers: https://www.drupal.org/docs/8/api/services-and-dependency-injection/dependency-injection-for-a-form.

10

If you'd like to do this with dependency injection and a service, then you can use RequestStack:

use Symfony\Component\HttpFoundation\RequestStack;

And define it like this:

protected $request;

public function __construct(..., RequestStack $request_stack) {
  ...
  $this->request = $request_stack->getCurrentRequest();
}

public static function create(ContainerInterface $container, ...) {
  return new static(
    ...
    $container->get('request_stack')
  )
}

And then declare it like this:

$this->request->getHost()
$this->request->getSchemeAndHttpHost()
9

Taking into account the "warnings about directly accessing the request object in this way in \Drupal::request" that Shaun Dychko mentioned, perhaps a good option to get the hostname is obtain it from the $base_url global variable, with the help of php function parse_url:

global $base_url;
$base_url_parts = parse_url($base_url);
$host = $base_url_parts['host'];
4

Code below is how core defines the [site:url] token. This works best in all cases for me in drupal 8 & 9:

$url_options = [
  'absolute' => TRUE,
  'language' => \Drupal::languageManager()->getCurrentLanguage(),
];
$site_url = Url::fromRoute('<front>', [], $url_options)->toString();
1
  • This adds language prefix if present, like 'drupal8.local/en/'
    – Dalmaz
    Sep 28, 2021 at 9:38
0
<?php
$url = \Drupal\Core\Url::fromUserInput('/', ['absolute' => TRUE])->toString();
?>
0
\Drupal::request()->getBaseUrl()

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.