0

I just had a Drupal 8 site break when moving it from a top-level domain on a server to a subdirectory on my desktop machine: apparently that subdirectory wants to be included in the URL as converted from routes. This threatens to ruin my sandbox environment so I would like to figure out 1) why this is happening and/or 2) what isn't portable about my code fragment below. I've been using

Url::fromRouteMatch($route_match)->toString()

to get the URL Alias of the current page: e.g., the RouteMatch passed as argument to the breadcrumb service. On the server, this returns a proper pathname relative to the top-level domain, for instance:

/dir1/dir2/dir3/myAlias

... but running the same code in my sandbox (http://localhost/mySite) includes the subdirectory name, as if Drupal is returning the URL relative my local web server's document root, instead of the root of my Drupal site:

/mySite/dir1/dir2/dir3/myAlias

I realise there may be better ways to get the current URL Alias (e.g., \Drupal::service('path.current')->getPath() and then passing it to \Drupal::service('path.alias_manager')->getAliasByPath, but I'd really like to convert the route itself since that's the argument to the breadcrumb builder in Drupal 8.

p.s., clarification, tentative answer: it is clear from comments below that the variable $base_path is expected to be used here, and that "base path" is how one refers to the name of the site subdirectory (if there is one). Neither of these were known to me when I submitted my question above and I can safely say they're not detailed in the Drupal 8 documentation either. Therefore the question becomes trivial: "How do I strip out that string from the provided URL?" and the answer is a matter of text processing:

global $base_path;
$route_url = Url::fromRouteMatch($route_match)->toString();
$alias_url = substr($route_url, strlen($base_path) - 1);

p.p.s., maybe a better answer: I think I know why comments suggest that finding the URL Alias from the request is the wrong approach, since the path.current service factors out any base path beautifully, without the gross string processing as above, and works fine in a breadcrumb builder:

$current_path = \Drupal::service('path.current')->getPath();
$alias_from_path = \Drupal::service('path.alias_manager')->getAliasByPath($current_path);

Sorry for all the fuss here: from my not knowing about the global variable $base_path or about how the Drupal services already deal with subdirectory installations. Looking forward to the answer as expressed by other contributors with an eye on the big picture.

10
  • I'm not sure what is wrong here? The proper behavior is to prepend the base directory onto the path when constructing a URL. In fact, the Drupal TestBot (the automated test runner), does all tests in a subdirectory to make sure that all of this logic works properly.
    – mpdonadio
    Commented Apr 18, 2016 at 14:31
  • "What is wrong" may only be that I have never known about this behaviour. My question would be answered as described if you would please tell me exactly what you mean by "base directory" - i.e. where it's defined in the Drupal documentation or code. Then I might understand how to factor it out of the Route as converted into a URL, to produce code that will work whether the site is based in a subdirectory or not.
    – rphair
    Commented Apr 18, 2016 at 14:57
  • I am seeing a method called Request::getBaseUrl and if that is what you were getting at then @MPD I think I understand you now, since test code would have a different base URL while running on the same site (?). Anyway if this static method is the correct way to determine the base URL (probably after getting a Request from the Route), then please present it as an answer & I'll mark it as such.
    – rphair
    Commented Apr 18, 2016 at 17:25
  • This is the same as the global $base_pathin D7, which still works in D8. If you have no intention to use a base path other then /in production, I would not use one in the sandbox and point a vhost mysite.localhost at /mysite.
    – 4uk4
    Commented Apr 18, 2016 at 18:39
  • You still haven't said what you actually want to do. toString() returns absolute paths, it starts with a /, so it must return the base path too, as those are the links that are printed on the page. It simply wouldn't work otherwise. ->getInternalPath() returns the path, without leading /. If you want it for the current path, then you can also use \Drupal::service('path.current')->getPath(), which is a bit strange as it does have a leading / but not the base path.
    – Berdir
    Commented Apr 18, 2016 at 19:41

1 Answer 1

1

Drupal 8 is very smart to detect in which environment it is running. If you have this path

/mySite/dir1/dir2/dir3/myAlias

then Drupal is installed in /mySite, but the root of the webserver is still in /.

If you want to get rid of /mySite you have to point your webserver at this directory. Usually you define a vhost with this path and choose a local sub domain, which is configured in the nameserver or your local host file.

With a correct configured vhost there shouldn't be any problems.

See https://httpd.apache.org/docs/current/vhosts/

6
  • This response suggests that Drupal is "smart" enough to determine the string difference between the document root and the pathname of the site root index.php file, while perhaps not smart enough (or friendly enough) to make this computed value available to the developer or themer. That is, there should be some code which will tell me what, if anything, is in the place of /mySite so any subdirectory can be removed from the beginning of the URL. I am familiar with vhosts, but using one in this case would a workaround for that missing information rather than an answer.
    – rphair
    Commented Apr 18, 2016 at 17:03
  • No, this is no work around. If you want to have a working sandbox, you need vhosts and subdomains.
    – 4uk4
    Commented Apr 18, 2016 at 18:11
  • Please let me understand this correctly, then... are you saying the only proper way to test a site that's moved from its own domain on the server is in another domain, i.e., a subdomain rather than a subdirectory? If that's true, how do the test suites mentioned by @MPD in the comments to the original posting know that they're running in a subdirectory?
    – rphair
    Commented Apr 18, 2016 at 18:48
  • Drupal has the ability to run in a subdirectory, which is a valid use case. And as drupal provides this functionality, this is included in the test routines. But if you don't want to use this in production, then don't use it in the sandbox. Because the subdirectory will always be visible in the browser path. Which is OK, when it is intentionally, but otherwise it makes things more complicated than needed.
    – 4uk4
    Commented Apr 18, 2016 at 19:00
  • Thanks to your comments @4k4 I have updated my planned test environment accordingly. The answer to my original question seems simply to remove $base_path from the request URL string whenever a URL Alias is needed. I appreciate your advice about testing strategy, and I can really understand why it's generally recommended due to what I've seen in this case.
    – rphair
    Commented Apr 18, 2016 at 20:12

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.