I know that the new thing to do in Drupal 8 is to do everything by route name rather than path but is there a way to create a route object by a path? The example I have is to set a form redirect to a specific page, created via the CMS. Using Drupal::url() requires a path name which would require me to hard code the node ID of the page I wish to use to go along with entity.node.canonical, which seems rather backwards.

Conversely I could programatically create the page in order to give it a specific route, but then that would defeat the purpose of using a CMS.

What would be the best way to generate a url for a redirect to a specific node without needing to rely on a hardcode id?

Thanks!

Comments

caxy4’s picture

I'm also interested in the answer to this question exactly.
Anyone out there know the answer?

slewazimuth’s picture

Short Answer:: Given a form which has a field of 'givenpath' and you wish to use that path to get the route:

// Get route name from path.
	$url_object = \Drupal::service('path.validator')->getUrlIfValid($form_state->getValue('givenpath'));
	$route_name = $url_object->getRouteName();
bbu23’s picture

you`d want to get also the parameters for the route name, especially if you`re doing a redirect or smth (of course, it depends on the case, but I thought it might be useful for someone):

$current_path = \Drupal::service('path.current')->getPath();
$url_object = \Drupal::service('path.validator')->getUrlIfValid($form_state->getValue($current_path));
$route_name = $url_object->getRouteName();
$route_parameters = $url_object->getrouteParameters();

$form_state->setRedirect($route_name, $route_parameters);
sriharsha.uppuluri’s picture

\Drupal::request()->get(Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_NAME)

\Drupal::service('path.validator')->getUrlIfValid('node/*')
pfrenssen’s picture

You can get this info from the Symfony router:

  $url = '/node/1';
  $request = \Symfony\Component\HttpFoundation\Request::create($url);
  $router = \Drupal::service('router.no_access_checks');
  $result = $router->matchRequests($url);

Now $result will contain an array with all the information you need. It contains the route name, the route object, the controller and title callback, even the entity the route belongs to.

mxh’s picture

Thanks for that, though there's maybe a small typo in there (method matchRequests() doesn't exist, maybe you meant matchRequest()). You may also consider exception handling here.
Following code works (for me) in 8.2.x:

<?php
$url = '/node/1';
$request = \Symfony\Component\HttpFoundation\Request::create($url);
$router = \Drupal::service('router.no_access_checks');
$match = [];
try {
  $match = $router->matchRequest($request);
}
catch (\Exception $e) {
  // No route found...
}
?>
avpaderno’s picture

The code can be simplified, as Drupal routers implement the match() method. (See Router::match().)

$match = [];
$path = '/node/1';
$router = \Drupal::service('router.no_access_checks');

try {
  $match = $router->match($path);
}
catch (\Exception $e) {
  // The route using that path hasn't been found,
  // or the HTTP method isn't allowed for that route.
}

// Use $match to get information about the route.
subhojit777’s picture

You can also obtain the route name from router table.

Your query will look like this:

SELECT `name`
FROM `router`
WHERE (`path` = '/my-path')

Just replace "my-path" with your path. You will get the route name, and then you can use it to generate urls like this \Drupal\Core\Url::fromRoute(route.name');

Regards,
Subhojit Paul

dejahvuuu’s picture

As simple as that.

joachim’s picture

Use RouteProvider::getRoutesByPattern(). Eg:

      $route_provider = \Drupal::service('router.route_provider');
      $found_routes = $route_provider->getRoutesByPattern('node/%/edit');
      $route_iterator = $found_routes->getIterator();
      if (count($route_iterator)) {
        // Route found.
      }
yeskmilo’s picture

Thank you!

Using RouteProvider::getRoutesByPattern() worked for me, I think that is the best way to find the route_name.

Best,

colan’s picture

$route_name = Url::fromUserInput($internal_path)->getRouteName();

See https://drupal.stackexchange.com/a/223465/2089 for details.

joachim’s picture

That doesn't work with an internal path such as 'node/%/edit'.

umed91’s picture

I have used it for a path like 'user/%/path' and it works great.

use Drupal\Core\Url;
$current_path = \Drupal::service('path.current')->getPath();
$route_name = Url::fromUserInput($current_path)->getRouteName();