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
- 223 reads