How can you contact us

2By phone at +40 749 014 360

If you still have problems, please let us know, by sending an email to info@westweb-solutions.com Thank you!

OFFICE HOURS

Mon-Fri 9:00AM - 6:00AM
Sat - 9:00AM - 1:00PM
Sundays by appointment only!

Drupal 8 - Dynamic Route

/ / Drupal 8

While improving the SEO for one of the projects I've worked on, I encountered the following problem:
- the system has a node listing for a given user (let's call it /user/%/cars); this is a simple view with a page display that receives the user argument from the route

- the problem is that the url is not SEO friendly


First, we'll add a link referencing the view page to the main menu by creating the custom_car.links.menu.yml

custom_car.my_cars:
  title: 'My Cars'
  route_name: view.cars.page_my_cars
  class: \Drupal\custom_car\Plugin\Menu\RouteMyCarsMenuLink
  menu_name: main
  weight: -1
  requirements:
    _user_is_logged_in: 'TRUE'

 

Next, we'll add the RouteMyCarsMenuLink class that will pass the current user id to the view route

<?php

namespace Drupal\custom_car\Plugin\Menu;

use Drupal\Core\Menu\MenuLinkDefault;

/**
 * Modifies the menu link to add current route path.
 */
class RouteMyCarsMenuLink extends MenuLinkDefault {

  public function getRouteParameters() {
    return [
      'arg_0' => \Drupal::currentUser()->id()
    ];
  }
}

 

Now, we should have a link to our cars page and this link has a user reference and not only a string like /my-cars.

This will allow us to create separate urls for each user.
 

Let's move on and create path aliases. We'll start this by downloading and enabling the Pathauto module.
Next, we will add the user pattern and run the batch update for existing users.

drupal 8 - dynamic route user pattern

Our next step is to use the above aliases in our route name (instead of using "/user/27/cars", we'll have  "/user/jane-doe/cars").

In order to achieve this, in our custom_car.module, we will implement the hook_entity_presave and create/update the user cars aliases.
 

/**
 * Implements hook_entity_presave().
 */
function custom_car_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
  switch ( $entity->getEntityTypeId() ) {
    case 'user':
      $uid = $entity->id();
      $user_cars_source = "/user/{$uid}/cars";
      $user_cars_alias = \Drupal::service('path.alias_manager')->getAliasByPath("/user/{$uid}") . '/cars';

      $query = \Drupal::database()
        ->select('url_alias', 'ua')
        ->fields('ua', ['pid', 'alias'])
        ->condition('ua.source', $user_cars_source);

      $results = $query->execute()->fetchAll();
      if ($results) {
        foreach ($results as $result) {
          \Drupal::database()
            ->update('url_alias')
            ->fields([
              'alias' => $user_cars_alias
            ])
            ->condition('pid', $result->pid)
            ->execute();
        }
      }
      else {
        \Drupal::service('path.alias_storage')->save($user_cars_source, $user_cars_alias, 'en');
      }
      break;

    default:
      break;
  }
}


 

You might also like to implement the hook_block_view_alter if you want to have a different title for each user.
 

/**
 * Implements hook_block_view_alter().
 */
function custom_car_block_view_alter($build, $block) {
  switch ($block->getPluginId()) {
    case 'page_title_block':
      $current_path = \Drupal::service('path.current')->getPath();
      if (preg_match('/^\/user\/([0-9]*)\/cars$/', $current_path, $matches)) {
        $title = t('My Cars');
        if (\Drupal::currentUser()->id() != $matches[1]) {
          $user = Drupal\user\Entity\User::load($matches[1]);
          $title = t('@name\'s cars', ['@name' => $user->getUsername()]);

          $request = \Drupal::request();
          if ($route = $request->attributes->get(\Symfony\Cmf\Component\Routing\RouteObjectInterface::ROUTE_OBJECT)) {
            $route->setDefault('_title', $title);
          }
        }
        $block->setTitle($title);
      }
      break;
  }
}


 

You might also like to implement the hook_entity_delete, since it does not make sense to keep outdated aliases.

Sign in your account to have access to different features

Forgot your details?

TOP