12
<?php

declare(strict_types=1);

namespace App\Controller\User;

use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;

#[Route('/users', name: 'user.')]
class UserController extends AbstractController
{
    #[Route(name: 'list')]
    public function list(#[CurrentUser] ?User $user, Request $request): Response { 
        dd($user->getFirstName());
    }

Say's Call to a member function getFirstName() on null

But I'm authorized. At the Symfony Profiler it shows that I'm logged in.

Env: PHP 8.0.11 Symfony 5.3.9

10
  • Which symfony version do you have? Commented Nov 2, 2021 at 11:33
  • Sure. "sensio/framework-extra-bundle": "^6.2", Commented Nov 2, 2021 at 12:09
  • 2
    Something else is broken in your code but not in evidence here.. I've tried the code above, and $user is correctly injected with the#[CurrentUser] attribute. cln.sh/yyXGsK No need to add nothing manually. The comment in the answer below is a red-herring, it only apples to custom param converters. Commented Nov 2, 2021 at 13:44
  • 1
    The issues comes from ParamConverter. When I set sensio_framework_extra: auto_convert: false, the #[CurrentUser] attribute, finally, works fine. Commented Nov 2, 2021 at 13:48
  • 3
    As per the documentation for the Argument Resolver usage: "Beware that this feature is already provided by the @ParamConverter annotation from the SensioFrameworkExtraBundle. If you have that bundle installed in your project, add this config to disable the auto-conversion of type-hinted method arguments:" Which seems to apply to both Custom and Built-In usage Commented Nov 2, 2021 at 14:39

3 Answers 3

10

The correct details on solution are provided by https://stackoverflow.com/users/1144627/will-b Symfony #[CurrentUser] attribute returns null

The issue is caused by enabled ParamConvertor (sensio/framework-extra-bundle). It can't resolve the User due to lack definitions of how to fetch the Entity from DB, so it sets the $user variable to null because of nullable #[CurrentUser] ?User $user . If you want to keep functionality of param converter and #[CurrentUser] attribute same time, you should disable auto convertion #

config/packages/sensio_framework_extra.yaml
sensio_framework_extra:
    request:
        converters: true
        auto_convert: false

And define route params each time manually. Sources: https://symfony.com/bundles/SensioFrameworkExtraBundle/current/annotations/converters.html https://symfony.com/blog/new-in-symfony-5-2-controller-argument-attributes https://symfony.com/doc/current/controller/argument_value_resolver.html

Solution to avoid such issues: Read the docs at 200% browser scale.

Sign up to request clarification or add additional context in comments.

1 Comment

It doesn't work at least for me, Symfony 6.2.
0

As pointed out by others, the problem is indeed the enabled ParamConverter in Sensio Framework Extra Bundle.

But instead of completely disabling it, you could change the typehinting in your Controller from User to UserInterface like this:

<?php

use Symfony\Component\Security\Core\User\UserInterface;
// ...

public function list(#[CurrentUser] ?UserInterface $user, Request $request): Response {
    assert($user instanceof User);
    dd($user->getFirstName());
}

Example of full Controller:

<?php

declare(strict_types=1);

namespace App\Controller\User;

use App\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Http\Attribute\CurrentUser;

#[Route('/users', name: 'user.')]
class UserController extends AbstractController
{
    #[Route(name: 'list')]
    public function list(#[CurrentUser] ?UserInterface $user, Request $request): Response {
        assert($user instanceof User);
        dd($user->getFirstName());
    }
}

1 Comment

Don't know why this got downvoted. This is what worked for myself without changing any global configs.
-1

if your controller extends "AbstractController" you can use $this->getUser() to get the current User.

in your list function you are not giving an user id neither an $user so $user is rationally null

#[Route('/users', name: 'user.')]
class UserController extends AbstractController
 {
#[Route(name: 'list')]
public function list( Request 
$request): Response { 
    dd($this->getUser()->getFirstName());
}

3 Comments

dd($this->getUser()->getFirstName()); Works fine. The #[CurrentUser] attributed has been presented with Attribute feature of PHP 8. I'm curious, is that a bug or I'm doing something wrong.
in Symfony doc, they talk about adding a new method to the ArgumentMetadata object passed to the argument value resolvers for this to work symfony.com/blog/…
Thanks. That's a good comment. Now I'm completely confused. What's the point of the #[CurrentUser] attribute if I have to manually add all the logic of User parameter resolving?

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.