3

I am still new to all the Symfony semantics. What would be the easiest way to change node canonical urls to be /article/[node-title] instead of /node/[node-id]? Following this documentation I tried the code (which I expected to produce at least a url structure like /article/[node-id])

<?php
/**
 * @file
 * Contains \Drupal\example\Routing\ExampleRoutes.
 */

namespace Drupal\example\Routing;
use Symfony\Component\Routing\Route;
/**
 * Defines dynamic routes.
 */
class ExampleRoutes {

  /**
   * {@inheritdoc}
   */
  public function routes() {
    $routes = array();
    // Declares a single route under the name 'example.content'.
    // Returns an array of Route objects. 
    $routes['entity.node.canonical'] = new Route(
      // Path to attach this route to:
      '/article/{node}',
      // Route defaults:
      array(
        '_controller' => '\Drupal\node\Controller\NodeViewController::view',
        '_title' => 'Hello'
      ),
      // Route requirements:
      array(
        '_permission'  => 'access content',
      )
    );
    return $routes;
  }

}
?>

But unfortunately it is not changing anything…

  • Lots to get through here I think :) See this for altering existing routes (I don't think your current method is correct). You'll also probably want to implement hook_entity_type_alter(), and use EntityTypeInterface::setLinkTemplate to override the entity type's canonical URL template. You may also need a custom parameter upcaster to get the node resolved from its title rather than the ID – Clive Jan 14 '15 at 11:55
  • Hey, thank you very much for the hints – do you have some code samples oder Drupal reference pages I could check out? By the way, I thought the method I used was right because the api reference suggested to use this in case one needs dynamic routes. – alexej_d Jan 14 '15 at 15:52
2

While theoretically now supported, that is not possible not like this.

You can not reliable load a node based on the node title, it is not guaranteed to be unique, and to become a practical URL, a number of replacements should be made, like replacing spaces, lowercasing it and so on.

Use the path alias system for this, just like in Drupal 7. We're maintaining an inofficial port of the pathauto module, that allows you to configure token patterns to automatically generate an alias for each node. You also need token.module, which you can get from here.

  • Would you happen to have some hints how to do this without a module? I am already attaching an invisible "slug" field to all nodes which is generated from the title and which is checked to be unique. I already know how to use the slug in a controller to load the node it is attached to but still I am not sure what the correct way would be… – alexej_d Jan 26 '15 at 18:47
  • Even then, you still want to just add an alias for your slug, that is much, much easier. For one thing, changing the upcasting would require that that field always exists, on all node types. If you don't want to use pathauto, just do the same as it does. Implement hook_node_insert()/update(), and call \Drupal::service('path.alias_storage')->save($entity->urlInfo()->getInternalPath(), $your_alias, $entity->language()->getId()). Note that pathauto also takes of updating the alias, and gives you a better UI that still allows a manual alias for exceptions. – Berdir Jan 27 '15 at 6:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.