I want change all /user, /user/* urls by /profile, /profile/* urls. From a custom module, I copied all user routes (found in /core/module/user/user.routing.yml) to my custom .routing.yml file. I replaced all "user*" paths by "profile*".

Now, I have the following.

mycustommodule.register:
  path: '/profile/register'
  defaults:
    _entity_form: 'user.register'
    _title: 'Create new account'
  requirements:
    _access_user_register: 'TRUE'

mycustommodule.pass:
  path: '/profile/password'
  defaults:
    _form: '\Drupal\user\Form\UserPasswordForm'
    _title: 'Reset your password'
  requirements:
    _access: 'TRUE'
  options:
    _maintenance_access: TRUE

mycustommodule.page:
  path: '/profile'
  defaults:
    _controller: '\Drupal\user\Controller\UserController::userPage'
    _title: 'My account'
  requirements:
    _user_is_logged_in: 'TRUE'

mycustommodule.login:
  path: '/profile/login'
  defaults:
    _form: '\Drupal\user\Form\UserLoginForm'
    _title: 'Log in'
  requirements:
    _user_is_logged_in: 'FALSE'
  options:
    _maintenance_access: TRUE

mycustommodule.login.http:
  path: '/profile/login'
  defaults:
    _controller: \Drupal\user\Controller\UserAuthenticationController::login
  methods: [POST]
  requirements:
    _user_is_logged_in: 'FALSE'
    _format: 'json'

mycustommodule.login_status.http:
  path: '/profile/login_status'
  defaults:
    _controller: \Drupal\user\Controller\UserAuthenticationController::loginStatus
  methods: [GET]
  requirements:
    _access: 'TRUE'
    _format: 'json'

mycustommodule.logout.http:
  path: '/profile/logout'
  defaults:
    _controller: \Drupal\user\Controller\UserAuthenticationController::logout
  methods: [POST]
  requirements:
    _user_is_logged_in: 'TRUE'
    _format: 'json'
    _csrf_token: 'TRUE'

mycustommodule.cancel_confirm:
  path: '/profile/{user}/cancel/confirm/{timestamp}/{hashed_pass}'
  defaults:
    _title: 'Confirm account cancellation'
    _controller: '\Drupal\user\Controller\UserController::confirmCancel'
    timestamp: 0
    hashed_pass: ''
  requirements:
    _entity_access: 'user.delete'
    user: \d+

mycustommodule.reset.login:
  path: '/profile/reset/{uid}/{timestamp}/{hash}/login'
  defaults:
    _controller: '\Drupal\user\Controller\UserController::resetPassLogin'
    _title: 'Reset password'
  requirements:
    _user_is_logged_in: 'FALSE'
  options:
    _maintenance_access: TRUE
    no_cache: TRUE

mycustommodule.reset:
  path: '/profile/reset/{uid}/{timestamp}/{hash}'
  defaults:
    _controller: '\Drupal\user\Controller\UserController::resetPass'
    _title: 'Reset password'
  requirements:
    _access: 'TRUE'
  options:
    _maintenance_access: TRUE
    no_cache: TRUE

mycustommodule.reset.form:
  path: '/profile/reset/{uid}'
  defaults:
    _controller: '\Drupal\user\Controller\UserController::getResetPassForm'
    _title: 'Reset password'
  requirements:
    _user_is_logged_in: 'FALSE'
  options:
    _maintenance_access: TRUE
    no_cache: TRUE

From my website, when I go to the http://mysite/profile, I'm redirected to the correct page (the user view), but the URL change automatically to http://mysite/user. I want keep the URL as http://mysite/profile. How can I do that? Is it possible?

up vote 6 down vote accepted

The routes you've defined are new routes with different names and this is the reason the standard routes are still in place. If you want to override the standard routes you would have to use the same route names like user.page:.

But this is not the best approach to alter multiple routes. Better use a route subscriber:

src/EventSubscriber/RouteSubscriber.php

<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\Routing\RouteSubscriberBase;
use Drupal\Core\Routing\RoutingEvents;
use Symfony\Component\Routing\RouteCollection;

class RouteSubscriber extends RouteSubscriberBase {

  protected function alterRoutes(RouteCollection $collection) {
    foreach ($collection->all() as $route) {
      if (strpos($route->getPath(), '/user') === 0) {
        $route->setPath(preg_replace('/^\/user/', '/profile', $route->getPath()));
      }
    }
  }


  public static function getSubscribedEvents() {
    $events = parent::getSubscribedEvents();

    $events[RoutingEvents::ALTER] = array('onAlterRoutes', -250);

    return $events;
  }

}

mymodule.services.yml

services:
  mymodule.route_subscriber:
    class: Drupal\mymodule\EventSubscriber\RouteSubscriber
    tags:
      - { name: event_subscriber }

Answer from 4k4 is good BUT it goes through all routes which is IMHO not right. Instead try this approach:

<?php

/**
 * @file
 * Contains \Drupal\mymodule\RouteOverride\PageManagerRoutesOverride.
 */

namespace Drupal\mymodule\RouteOverride;

use Drupal\Core\Routing\RouteBuildEvent;
use Drupal\Core\Routing\RoutingEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Component\Discovery\YamlDiscovery;

/**
 * Class PageManagerRoutesOverride
 * Overrides paths for the Page Manager module to suit the structure of mymodule.
 */
class PageManagerRoutesOverride implements EventSubscriberInterface {

  /**
   * Path to the root of the project.
   *
   * @var string
   */
  protected $root;

  /**
   * The module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * Constructs a new PageManagerRoutesOverride object.
   *
   * @param string $app_root
   *   The current application root path.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_hander
   *   The module handler service.
   */
  public function __construct($app_root, ModuleHandlerInterface $module_hander) {
    $this->root = $app_root;
    $this->moduleHandler = $module_hander;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[RoutingEvents::ALTER] = 'alterRoutes';
    return $events;
  }

  /**
   * Alters existing routes.
   *
   * @param \Drupal\Core\Routing\RouteBuildEvent $event
   *   The route building event.
   */
  public function alterRoutes(RouteBuildEvent $event) {
    // See if the Page Manager UI module is enabled.
    if (!$this->moduleHandler->moduleExists('page_manager_ui')) {
      return;
    }

    // Page manager has just too many routes and is still quite prone to changes
    // so instead of overriding them manually, we'll use the actual route definitions.
    $module_directory = $this->moduleHandler->getModule('page_manager_ui')->getPath();
    $discovery = new YamlDiscovery('routing', [$this->root . '/' . $module_directory]);
    $route_files = $discovery->findAll();

    // Get the route names.
    if (isset($route_files['page_manager_ui'])) {
      $route_names = array_keys($route_files['page_manager_ui']);
    } else {
      $route_names = [];
    }

    // Fetch the collection which can be altered.
    $collection = $event->getRouteCollection();

    // Process the routes.
    foreach ($route_names AS $route_name) {
      // Fetch the route.
      $route = $collection->get($route_name);

      // Set the new path.
      $route_path = strtr($route->getPath(), [
        '/admin/structure/page_manager' => '/mymodule/content/page-builder',
        '/admin/structure/page_variant' => '/mymodule/content/page-builder'
      ]);
      $route->setPath($route_path);

      // Some custom alterations.
      switch ($route_name) {
        case 'entity.page.collection':
          $route->setDefault('_title', 'Page builder');
          break;
      }
    }
  }

}

And the service:

mymodule.page_manager_routes_override:
  class: Drupal\mymodule\RouteOverride\PageManagerRoutesOverride
  arguments: ['@app.root', '@module_handler']
  tags:
    - { name: event_subscriber }
  • @ivan-jaros How to do it in D7? – Umair May 5 '17 at 13:42
  • @Umair you can use hook_menu_alter(I think) and probably hook_link_alter(or something like that) and hook_boot(to add redirect) but easier would be to use path alias. Depends on the needs. – user21641 May 5 '17 at 14:51

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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