In honeypot's hook_install(), the current code (which worked until #2343759: Provide an API function to replace url()/l() for external urls was committed) used l() inside hook_install to build a link to the honeypot configuration page:

/**
 * Implements hook_install().
 */
function honeypot_install() {
  drupal_set_message(t("Honeypot installed successfully. Please !link to protect your forms from spam bots.", [
    '!link' => l(t('configure Honeypot'), 'admin/config/content/honeypot'),
  ]));
}

Using the new method of building a Url() and passing it to \Drupal::l() (see example below) throws the exception Uncaught PHP Exception Symfony\\Component\\Routing\\Exception\\RouteNotFoundException: "Route "honeypot.config" does not exist."

/**
 * Implements hook_install().
 */
function honeypot_install() {
  $config_url = Url::fromRoute('honeypot.config');
  drupal_set_message(t("Honeypot installed successfully. Please !link to protect your forms from spam bots.", [
    '!link' => \Drupal::l(t('configure Honeypot'), $config_url),
  ]));
}

It seems that hook_install may be called prior to a new module's routes being added/available to Drupal, so technically, you can't use any new routes for anything within hook_install() (which is a regression...). Would the alternative simply be to use the hardcoded path (instead of a module-defined route)?

Comments

geerlingguy’s picture

Apparently the hardcoded-path workaround won't work, either (just noticed, after reading the docs, that fromUri() only works with full Uri's, not internal paths. I guess I could hack around and get the current Uri, then pass that into fromUri, then see if it lets me create a Url... but at that point I might as well just code the link by hand!).

/**
 * Implements hook_install().
 */
function honeypot_install() {
  $config_url = Url::fromUri('admin/config/content/honeypot');
  drupal_set_message(t("Honeypot installed successfully. Please !link to protect your forms from spam bots.", [
    '!link' => \Drupal::l(t('configure Honeypot'), $config_url),
  ]));
}

Throws:

Uncaught PHP Exception InvalidArgumentException: "You must use a valid URI scheme. Use base:// for a path, e.g., to a Drupal file that needs the base path. Do not use this for internal paths controlled by Drupal." at /var/www/drupal/core/lib/Drupal/Core/Url.php line 206
geerlingguy’s picture

Title: Drupal::l() can't be used in hook_install() - Symfony throws "Route does not exist" » Drupal::l() can't be used for internal paths in hook_install() - Symfony throws "Route does not exist"

Clarifying title to note that only internal paths/routes are affected (in hook_install() and potentially some other places...).

almaudoh’s picture

Technically, if you use Url::fromUri('base://admin/config/content/honeypot'), it should work. But that is not recommended because it bypasses D8's internal routing and access checking mechanisms. :( Then again, it's in hook_install, so...

dawehner’s picture

Status: Active » Fixed

Yeah for now use base:// but there might be an API for what you want in the future, see #2346189: Denormalizing paths into route names/parameters is brittle / broken

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

geerlingguy’s picture

Status: Closed (fixed) » Closed (works as designed)

This issue wasn't ever technically 'fixed', should probably be "works as designed"; however, the following code was working in 8.0.x:

$config_url = Url::fromUri('base://admin/config/content/honeypot');

...and is not in 8.1.x. See #2676888: Installing Honeypot via UI results in unexpected error due to unavailable honeypot.config route. I might just have to remove that UX convenience entirely, as it's causing me more trouble than it's worth :(.