Two ways to get the internal path of a URL in Drupal
I recently encountered a problem in the (excellent) Schemadotorg module.
Basically, when comparing two Drupal paths the first one resolves to the ugly path (internal, node/NID
) and another one to the alias, the nice path that we usually auto-generate with modules like pathauto (/articulos/sección/nombre-del-artículo
).
$url = Url::fromRouteMatch($route_match);
$path = parse_url($url->toString(), PHP_URL_PATH); // <-- /aliased/path
$front_path = $this->configFactory
->get('system.site')
->get('page.front'); // < -- /node/NID
if ($path === $front_path) // <------ FAIL!
Therefore, when comparing paths to see if they belong to the same resource a false negative could be given.
This is because the second path uses the toString() method of the Drupal Url object which always returns the processed path (alias being the most common processor):
$url->toString(); // Returns /alias/to/resource
How can we get the unprocessed path?
The simple answer is that there is a second method:
$url->getInternalPath(); // Returns resource/ID
But the problems were not going to end here. The comparison was still failing because the first path comes with slash (/node/NID
) while the getInternalPath()
method returns the path without slash (node/NID
).
This could be solved by concatenating the slash, but this kind of manual solutions are always a bit scary because any Drupal update could knock it down.
Fortunately, there is a second less known way: we can change the path_processing
option in the URL object to bypass the processing:
$url->setOption('path_processing', false)->toString()
In this case, toString()
is executed without executing path processors (the alias amongst them) and the result is, finally, /node/NID
.