symfony получение дополнительных методов пользователя из сессии в AbstractController
Primary tabs
Примечание: проверено на Symfony 7
Задача
Есть класс контроллера:
namespace App\Controller;
// ...
use App\Entity\Post;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/post')]
class PostController extends AbstractController
{
// ...
#[IsGranted('ROLE_USER')]
#[Route('/new', name: 'app_post_new', methods: 'POST')]
public function new(Request $request): Response
{
$post = new Post();
// ...
$post->setUserId($this->getUser()->getId());
// ...
}
}
Есть сущность пользователя:
namespace MyNamespace;
use Symfony\Component\Security\Core\User\UserInterface;
class User implements UserInterface
{
private $id;
private $username;
private $roles = [];
public function getId(): int
{
return $this->id;
}
// ...
}
В методе new() контроллера PostController, строке 22, мы хотим установить id авторизованного пользователя, автора поста. Такой код работает, но IDE подсвечивает getId() в этой строке как ошибку и выводит сообщение наподобие "Undefined method 'getId'." Если перейти к объявлению метода getUser() абстрактного контроллера, то увидим, что тип возвращаемого значения ?UserInterface. UserInterface содержит только 3 метода: getRoles(), eraseCredentials() и getUserIdentifier(). Они будут доступны в подсказках IDE при вводе $this->getUser()->... в строке 22 контроллера PostController. UserInterface не содержит метода getId(), из-за чего и выдается ошибка в IDE.
Варианты решения
Решение 1
В пользоватетельский PostController добавить в зависимости атрибут CurrentUser и класс пользователя:
use MyNamespace\User; use Symfony\Component\Security\Http\Attribute\CurrentUser;
Далее изменить метод new():
#[IsGranted('ROLE_USER')]
#[Route('/new', name: 'app_post_new', methods: 'POST')]
public function new(Request $request, #[CurrentUser] User $user): Response
{
$post = new Post();
// ...
$post->setUserId($user->getId());
// ...
}
Решение 2
В PostController добавить в зависимости класс пользователя:
use MyNamespace\User;
и добавить аннотацию:
/**
* @method User getUser()
*/
#[Route('/post')]
class PostController extends AbstractController
{
// ...
}
которая заменяет тип возвращаемого значения встроенного метода getUser() контроллера AbstractController.
Возможен и дугой вариант такого решения - создать дополнительный контроллер, например:
namespace App\Controller;
use MyNamespace\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
/**
* @method User getUser()
*/
class BaseController extends AbstractController
{
}
Далее наследовать свои контроллеры от BaseController вместо AbstractController.
Источники
- Log in to post comments
- 912 reads