6

I want to redirect every users page to front page? like if user page url is /user/97 then it redirect to front page if user is not administrator. I want user page inaccessible to other users but only administrators.

How can I achieve this?

I tried doing like this:

<?php

namespace Drupal\myisu_ubit\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
// use Drupal\user\Entity\User;

 /**
   * Listens to the dynamic route events.
   */
 class RouteSubscriber extends RouteSubscriberBase {

 /**
  * {@inheritdoc}
  */
 protected function alterRoutes(RouteCollection $collection) {
   // Change the route associated with the user profile page (/user, /user/{uid}).
   if ($route = $collection->get('user.page')) {
      $route->setPath('/');
   } 
 }

}

module.services.yml:

services:
  user_profile.route_subscriber:
     class: Drupal\module\Routing\RouteSubscriber
     tags:
        - { name: event_subscriber }

What am I doing wrong here?

8
  • Pretty easy to do with code, there is also Rules, and a handful of contributed modules that provide this.
    – Kevin
    Nov 9, 2018 at 20:59
  • How to?please show me. I tried with controllers and routes but unsuccessful also I don't wanna use Rules
    – tasqyn
    Nov 9, 2018 at 21:02
  • Why do you need controllers and routes? The most basic level only needs to use hook_form_alter. drupal.stackexchange.com/a/223452/57 you can look at the logged in user and inspect their roles, then do the redirect.
    – Kevin
    Nov 9, 2018 at 21:04
  • 1
    Possible duplicate of Redirect after user login
    – Kevin
    Nov 9, 2018 at 21:04
  • For some reason I read this as "after logging in".
    – Kevin
    Nov 9, 2018 at 21:06

2 Answers 2

6

Solved using EventSubscriber like this:

services:
  my_module.event_subscriber:
    class: Drupal\my_module\EventSubscriber\MyModuleSubscriber
    tags:
       - {name: event_subscriber}

And MyModuleSubscriber:

namespace Drupal\my_module\EventSubscriber;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\views\Views;
use Drupal\views\ViewExecutable;
use Drupal\user\Entity\User;
use Drupal\Core\Url;

class MyModuleSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  public function checkForRedirection(GetResponseEvent $event) {
    $request = \Drupal::request();
    $requestUrl = $request->server->get('REQUEST_URI', NULL);
    $userID = \Drupal::currentUser()->id();
    $user = User::load($userID);
    $uid = $user->get('uid')->value;
    $roles = $user->getRoles();
    $userPage = "/user/" . $userID;
    if (
      $userID !== '1' && 
      !in_array('administrator', $roles) &&
      $requestUrl == $userPage
    ) {
        $path =  \Drupal::service('path.alias_manager')->getAliasByPath('/');
      $event->setResponse(new RedirectResponse($path, 301));
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkForRedirection');
    return $events;
  }

}

I don't know if it is the correct way to do this but it solves my problem.

1
  • 2
    This is the correct way to redirect, in general. But in this case, to make pages inaccessible, the Drupal way would be to use permissions. Then you can redirect on the resulting 403 exception to show the frontpage instead.
    – 4uk4
    Nov 11, 2018 at 23:12
2

Here's an updated example for Drupal 9.

Notes

  • This does not check for an administrator role; instead, it checks for the administer content permission, which all admins have on my site. Make sure the same is true for your site or modify the code.
  • This does a redirect on ANY user profile page, not just the user's own profile page. This is different from @tasqyn's code.
  • This uses route matching instead of hard-coding the user profile path. This is important because otherwise it will break if you change the user path with something like the Rename Admin Paths module.

mymodule/mymodule.services.yml

services:
  my_subscriber:
    class: Drupal\mymodule\EventSubscriber\MyEventSubscriber
    arguments: ['@request_stack', '@current_route_match', '@current_user']
    tags:
      - { name: 'event_subscriber' }

mymodule/src/EventSubscriber/MyEventSubscriber.php

<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\Routing\CurrentRouteMatch;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Event Subscriber MyEventSubscriber.
 */
class MyEventSubscriber implements EventSubscriberInterface {

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The current route match.
   *
   * @var \Drupal\Core\Routing\CurrentRouteMatch
   */
  protected $currentRouteMatch;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected AccountInterface $currentUser;

  /**
   * MyEventSubscriber constructor.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Routing\CurrentRouteMatch $current_route_match
   *   The current route match.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   */
  public function __construct(RequestStack $request_stack, CurrentRouteMatch $current_route_match, AccountInterface $current_user) {
    $this->requestStack = $request_stack;
    $this->currentRouteMatch = $current_route_match;
    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events = [
      KernelEvents::REQUEST => 'redirectAuthUsersOnProfile',
    ];
    return $events;
  }

  /**
   * {@inheritdoc}
   */
  public function redirectAuthUsersOnProfile(RequestEvent $event) {
    $routeName = $this->currentRouteMatch->getRouteName();
    if (!$this->currentUser->hasPermission('administer content') &&
      $routeName === 'entity.user.canonical') {
      $response = new TrustedRedirectResponse('/webapp/index.html', 302);
      $event->setResponse($response);
    }
  }

}
1
  • Just want to add that you might want to use <front> instead of hardcoding the URL: $url = Url::fromRoute('<front>')->toString(); $response = new RedirectResponse($url);
    – NicklasF
    Dec 11, 2023 at 13:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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