-1

I have a problem with event subscriber. Here is the error:

The website encountered an unexpected error. Please try again later. Error: Call to a member function getRouteName() on null in Drupal\hello_world\EventSubscriber\HelloWorldRedirectSubscriber->onRequest() (line 58 of modules\custom\src\EventSubscriber\HelloWorldRedirectSubscriber.php).

and my code is:

<?php

namespace Drupal\hello_world\EventSubscriber;

use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
//use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Drupal\Core\Routing\currentRouteMatch;
use Drupal\Core\Routing\LocalRedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Drupal\Core\Url;


/**
 * Subscribers to the Kernel Request event and redirects to the
 * homepage when the user has the "non_grata" role.
 */
class HelloWorldRedirectSubscriber implements EventSubscriberInterface {

  /**
   *  @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser; // Store the current user as a class property

  /**
   * HelloWorldRedirectSubscriber constructor.
   *
   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
   */
  public function __construct(AccountProxyInterface $currentUser) {
    $this->currentUser = $currentUser;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    // $events['kernel.request'][] = ['onRequest', 0];
    // più elegante:
    $events[KernelEvents::REQUEST][] = ['onRequest', 0];
    return $events;
  }

  /**
   * Handler for the kernel request event.
   *
   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event
   */

  public function onRequest(GetResponseEvent $event) {
    //$request = $event->getRequest();
    //$path = $request->getPathInfo();
    // if ($path !== '/hello')
    // {
    //   return;
    // } BEST PRACTICE FOR KEEP DYNAMICITY: currentRouteMatch Service
    $route_name = $this->currentRouteMatch->getRouteName();

    // check against the route name (and not path name)
    if ($route_name !== 'hello_world.hello')
    {
      return;
    }

    $roles = $this->currentUser->getRoles();

    if (in_array('inaccettabile', $roles)) {
      // $event->setResponse(new RedirectResponse('/'));
      $url = Url::fromUri('internal:/');
      // LocalRedirectResponse class redirect the user to a local (safe) path
      $event->setResponse(new LocalRedirectResponse($url->toString()));
    }
  }
}

I cannot figure out what could be the problem. :\

  • 3
    The error tells you the issue, "Call to a member function getRouteName() on null" and you're doing getRouteName() on $this->currentRouteMatch which doesn't exist (the erroe says its null). Take a look at this (api.drupal.org/api/drupal/…) and click the "view source" to see an example and see that they are doing with "currentRouteMatch" – Leigh May 16 at 15:38
1

An event subscriber is just a service tagged with name: event_subscriber and implemented by a class implementing the EventSubscriberInterface interface.

The code you are using is supposed to use a service, but the reference to that service isn't defined as parameter of the class constructor, nor it is initialized in any way.

The MainContentViewSubscriber class is an example of event subscriber implementation that uses the current_route_match service. The key parts of that event subscriber (the main_content_view_subscriber service) are:

  • The service definition

    class: Drupal\Core\EventSubscriber\MainContentViewSubscriber
    arguments:
      - '@class_resolver'
      - '@current_route_match'
      - '%main_content_renderers%'
    tags:
      - { name: event_subscriber }
    
  • The constructor of the MainContentViewSubscriber class

    public function __construct(ClassResolverInterface $class_resolver, RouteMatchInterface $route_match, array $main_content_renderers) {
      $this->classResolver = $class_resolver;
      $this->routeMatch = $route_match;
      $this->mainContentRenderers = $main_content_renderers;
    }
    

The current_route_match service is defined as argument of the event subscriber service, and it's defined as parameter of constructor of the event subscriber class.

Your event subscriber service/class needs to do the same. Of course, the other services used from the class I used as example aren't required in your case, so they can be omitted.

  • my service.yml is: hello_world.redirect_subscriber: class: \Drupal\hello_world\EventSubscriber\HelloWorldRedirectSubscriber arguments: ['@current_user'] tags: - { name: event_subscriber } The problem is that I have read that code on a book so I dunno why it doesn't work.. – Emilio May 17 at 8:59
  • 1
    The service arguments should be ['@current_user', '@current_route_match'], the constructor arguments should be $currentUser, $currentMatch, and the constructor should assign those values to two properties ($this->currentUser = $currentUser; $this->currentMatch = $currentMatch;). (The class should then define a new property.) – kiamlaluno May 17 at 9:05

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.