6

I need to get the global $user object in Drupal 8. I did $account = \Drupal::currentUser(); in the definition of getSubscribedEvents() (a static method) inside a class file.

I get the following error when running drush cr:

exception
[error] 'Drupal\Core\DependencyInjection\ContainerNotInitializedException' with message '\Drupal::$container is not initialized yet. \Drupal::setContainer() must be called with a real container.' in /Applications/MAMP/htdocs/drupal-8.0.x-dev/core/lib/Drupal.php:129

What is wrong in my code?

  • You don't need to use any namespace $account = \Drupal::currentUser();, will give current user object. To get user ID, you can use \Drupal::currentUser()->id(); directly. – Yogesh Jun 30 '16 at 9:55
  • Using $account = \Drupal::currentUser(); itself is giving the error. – neha Jun 30 '16 at 10:08
  • @JyotiBohra you still getting error with my answer ? – Sanjay Jun 30 '16 at 10:13
  • Which version of Drush are you using? seems like a Drush version issue, check here. – Yogesh Jun 30 '16 at 10:33
  • @Sanjay Yes i am getting the same error with your code as well. – neha Jun 30 '16 at 10:40
10

You can not get the current user in getSubscribedEvents()

That is not possible and not needed. There is no container at this point.

The only thing you may do in there is returned a list of events you want to register to. This information is then stored in the compiled container and must be identical for all requests, it must not be conditional.

Any logic needs to be inside the methods you register there.

9

Since you are using a getSubscribedEvents() static method, I get you are implementing an event subscriber. In this case, you don't access \Drupal::currentUser() (and any static method returning a service that \Drupal exposes) in that method since it would be getting called too early, when Drupal has not yet initialized the dependency container.
That static method is supposed to return a static array describing the events to which the module wants to subscribe; the methods used to subscribe to the events will eventually take a different action basing on the user currently logged-in, and the user permissions that user account has.

Event subscribers are services, and as such they get their dependency injected. Instead of using \Drupal::currentUser(), you define @current_user as one of the arguments of your service, which is what the authentication_subscriber service does.

class: Drupal\Core\EventSubscriber\AuthenticationSubscriber
arguments:
  - '@authentication'
  - '@current_user'
tags:
  - { name: event_subscriber }

If you look at AuthenticationSubscriber::__construct(), you will see how it gets the current user object.

public function __construct(AuthenticationProviderInterface $authentication_provider, AccountProxyInterface $account_proxy) {
  $this->authenticationProvider = $authentication_provider;
  $this->filter = ($authentication_provider instanceof AuthenticationProviderFilterInterface) ? $authentication_provider : NULL;
  $this->challengeProvider = ($authentication_provider instanceof AuthenticationProviderChallengeInterface) ? $authentication_provider : NULL;
  $this->accountProxy = $account_proxy;
}

In your case, I would use the following code.

mymodule.services.yml

services:
  mymodule.eventsubscriber:
    class: Drupal\mymodule\EventSubscriber\MyModuleSubscriber
    arguments:
      - '@current_user'
    tags:
      - { name: event_subscriber }

src/EventSubscriber/MyModuleSubscriber.php

namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MymoduleSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  static function getSubscribedEvents() {
    // Return the array describing the events to which you subscribe.
  }

  public function __construct(AccountProxyInterface $account_proxy) {
    $this->accountProxy = $account_proxy;
  }

}

Notice that @current_user is an instance of AccountProxyInterface, so for example, you can check the user has some user permissions with $this->accountProxy->hasPermission().

  • That's all correct, the problem is that OP is trying to call the current user in getSubscribedEvents, which simply is not possibe. See my answer. Using it correctly will then involve your approach. – Berdir Jun 30 '16 at 12:24
  • @Berdir In fact, I said "Also, EventSubscriberInterface::getSubscribedEvents() just returns an array of events to which the module wants to subscribe. It's those methods associated to the event that eventually do something basing on the current logged-in user." – kiamlaluno Jun 30 '16 at 12:29
  • Right, I overlooked that. I'd recommend to move that at the top and make it a bit strong, along the lines of what I wrote. Because clearly @JyotiBohra didn't see it either :) – Berdir Jun 30 '16 at 13:07
  • This is working fine for admin users but it is showing anonymous user with id = 0 for other authenticated users. – neha Jul 20 '16 at 13:26
  • @njb You need to ask another question where you show your code. Since you didn't show your code, I cannot answer about that. You can't edit the question to add your code, or you would change the question meaning. Notice also that my code doesn't contain the part you didn't show, since I can't know to which events you are trying to subscribe. – kiamlaluno Jul 20 '16 at 13:57
2

Here is my whole piece of code which works fine now:

Inside my_module.service.yml

services:
  myModule.event_subscriber:
    class: Drupal\my_module\EventSubscriber\MymoduleSubscriber

    tags:
      - {name: event_subscriber}

Inside MymoduleSubscriber.php

<?php

namespace Drupal\my_module\EventSubscriber;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class myModule implements EventSubscriberInterface {



  public function xyz(GetResponseEvent $event) {
    $user_id = $this->accountProxy->id();
    if($user_id) {
    }
  }
  /**
   * {@inheritdoc}
   */
  static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('xyz');
    return $events;

  }

  public function __construct() {
    $user = \Drupal::currentUser();
    $this->accountProxy = $user;
  }

}
  • That is not the way you check ìf the user has logged in; there is a method for that. – kiamlaluno Jul 20 '16 at 14:01
1

You have to use namespace for load the current user object.

// Load the current user.
$user = \Drupal\user\Entity\User::load(\Drupal::currentUser()->id());

// get field data from that user

$email = $user->get('mail')->value;
$name = $user->get('name')->value;
  • This answer doesn't have to do anything with the question. First of all: when using static calls you don't have to use namespaces, or whatsoever. Secondly: he/she got a quiet different exception, it's not like he/she doesn't know who to get values from the user object. – ssibal Jun 30 '16 at 10:03
  • when she asked her question, it was without edited and she asked for namespace missing, so i answer that according to that and nothing wrong with my answer also that you put down my answer. – Sanjay Jun 30 '16 at 10:10
  • The first revision gave the same exact information you see in the current revision. – kiamlaluno Jun 30 '16 at 11:02
  • 1
    This statement: "You have to use namespace for load the current user object": It's irreveleant, that he/she is trying to load it in a evensubscriber service, where (from some reason) the Drupal container is not initialized yet. This problem has nothing to do with namespaces whatsoever. – ssibal Jun 30 '16 at 11:12
  • 1
    Still, with the way the title of the question is phrased, this is the best answer. Google brought me here. – RaisinBranCrunch Mar 28 '17 at 1:08

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.