Last updated comment #11

So. Um. What?

D7

      $items['create_account'] = l(t('Create new account'), 'user/register', array(
        'attributes' => array(
          'title' => t('Create a new user account.'),
          'class' => array('create-account-link'),
        ),
      ));

D8

      $items['create_account'] = Drupal::linkGenerator()->generate(t('Create new account'), 'user_register', array(), array(
        'attributes' => array(
          'title' => t('Create a new user account.'),
          'class' => array('create-account-link'),
        ),
      ));

Replacing l() with Drupal::linkGenerator()->generate()? Seriously?

We need to replace this with something that doesn't expose underlying API details to normal developers. Suggestion: Drupal::link(). Otherwise, expect developers to go back to hard-coding <a> tags.

#2078285: Add short-cut methods to the \Drupal class for generating URLs and links from routes
#2073811: Add a url generator twig extension
#2073813: Add a UrlGenerator helper to FormBase and ControllerBase

Comments

tim.plunkett’s picture

$items['create_account'] = array(
  '#type' => 'link',
  '#title' => t('Create new account'),
  '#href' => 'user/register',
  '#options' => array(
    'attributes' => array(
      'title' => t('Create a new user account.'),
      'class' => array('create-account-link'),
    ),
  ),
);

There is an issue to add a #route_name for #type => link

pwolanin’s picture

@tim.plunkett - #route_name is done now in the link generator patch.

re: DX see: #2078285: Add short-cut methods to the \Drupal class for generating URLs and links from routes - I might consider this duplicate?

      $items['create_account'] = Drupal::l(t('Create new account'), 'user_register', array(), array(
        'attributes' => array(
          'title' => t('Create a new user account.'),
          'class' => array('create-account-link'),
        ),
      ));

basically we just need to bikeshed Drupal::l() or Drupal::link()

tim.plunkett’s picture

Great, then

$items['create_account'] = array(
  '#type' => 'link',
  '#title' => t('Create new account'),
  '#route_name' => 'user_register',
  '#options' => array(
    'attributes' => array(
      'title' => t('Create a new user account.'),
      'class' => array('create-account-link'),
    ),
  ),
);

And yes, I'd consider this a dupe, but leaving that to @webchick.

pwolanin’s picture

pwolanin’s picture

Also, I would be totally fine if we tweaked l() and url() to take a path OR an array of route name and parameters, though many would barf...


function url($path = NULL, array $options = array()) {
  $generator = Drupal::urlGenerator();
  try {
    if (is_array($path)) {
      list($route_name, $route_parameters) = $path;
      $url = $generator->generateFromRoute($route_name, $route_parameters, $options);
    }
    else {
      $url = $generator->generateFromPath($path, $options);
    }
  }
  catch (GeneratorNotInitializedException $e) {
    // Fallback to using globals.
    // @todo Remove this once there is no code that calls url() when there is
    //   no request.
    global $base_url, $base_path, $script_path;
    $generator->setBasePath($base_path);
    $generator->setBaseUrl($base_url . '/');
    $generator->setScriptPath($script_path);
    $url = $generator->generateFromPath($path, $options);
  }
  return $url;
}
msonnabaum’s picture

I very much agree with tim's approach. We should take a hard look at where these functions are used, because I dont get what the use case is for having these is outside the theme layer.

webchick’s picture

Sorry, I didn't see #2078285: Add short-cut methods to the \Drupal class for generating URLs and links from routes before I posted this. But now there is more discussion here, so I'm unsure what to do. I think maybe closing the other one as a dupe and moving the patches over here (but I don't want to do that myself because Dreditor will then mis-attribute them to me). Else, we can close this one and re-write the issue summary of the other and escalate to critical (I don't have time to do this right now, but can sometime over the weekend if no one beats me to it).

thedavidmeister’s picture

There will be a perf hit using render arrays for all links instead of sending them directly to l()/generator as there are extra function calls and processing involved in drupal_render() and drupal_pre_render_link().

msonnabaum’s picture

That is not a performance hit worth considering.

pwolanin’s picture

The biggest use outside the theme layer is for translated text and help text where we frequently call url() now.

Other than that, I agree they should rarely need to be called directly.

@webchick - the only thing to decide really is the method name - I think we should leave the other issue open for discussion of the patch to add Drupal::l(), and we should either close this one or make it a meta.

pwolanin’s picture

Title: Fix the DX of the link generator » [meta] Fix the DX of the link generator

change title

pwolanin’s picture

Issue summary: View changes

...

tim.plunkett’s picture

Status: Active » Closed (duplicate)

This was left open until the issue summary of #2078285: Add short-cut methods to the \Drupal class for generating URLs and links from routes was rewritten, but that already got committed.

thedavidmeister’s picture

thedavidmeister’s picture

Issue summary: View changes

Updated issue summary.

dawehner’s picture

These days this would look like the following:

 $items['create_account'] = (new Link(t('Create new account'), Url::fromRoute('user.register', array(), array(
        'attributes' => array(
          'title' => t('Create a new user account.'),
          'class' => array('create-account-link'),
        ),
      ))); // modulo more or less ")"
dawehner’s picture

Issue summary: View changes

But this could be certainly moved to

 $items['create_account'] = Link::fromUrl(t('Create new account'), Url::fromRoute('user.register', array(), array(
        'attributes' => array(
          'title' => t('Create a new user account.'),
          'class' => array('create-account-link'),
        ),
      )))->toString(); // modulo more or less ")"