Search code examples
phpsymfonysymfony5

Symfony type hinting for custom User class


I am trying to get type hinting to work with a custom User class in the Symfony 5.4 Security bundle and PHP 7.4. So I have this User class:

// src/Security/User.php
<?php

namespace App\Security;

class User implements JWTUserInterface
{
    private int $customProp
    
    public function getCustomProp() {
        return $this->customProp;
    }
    ...
}

But whenever I try to access the user in some service I do not get type hints for the customProp

// src/Service/MyService.php
<?php

namespace App\Service;

use Symfony\Component\Security\Core\Security;

class MyService
{
    private int $customProp;

    public function __construct(Security $security) {
        $this->myCustomProp = $security->getUser()->getCustomProp();
    }                                               ~~~~~~~~~~~~~

}

The message I get is

Undefined method 'getCustomProp'.

But the value is there and the code works, I simply can not get the IDE to understand that my custom User class offers this method.


Solution

  • You're getting this issue because Security::getUser() is a native Symfony function that returns the native Symfony UserInterface, and that UserInterface does not define getCustomProp(). The IDE does not know that the object being returned is an instance of your custom User class. You could explicitly tell it so like this:

    public function __construct(Security $security) {
        /** @var \App\Security\User $user */
        $user = $security->getUser();
        $this->myCustomProp = $user->getCustomProp();
    }
    

    Alternatively, instead of initializing a copy of the variable in the constructor, you might make a method with a typehinted return:

    class MyService {
        protected Security $security;
    
        public function __construct(Security $security) {
            $this->security = $security;
        }
    
        protected function getUser(): \App\Security\User {
            return $this->security->getUser();
        }
    
        public function doSomething() {
            // Now your IDE knows that getUser() is an instance of your custom class.
            $this->getUser()->getCustomProp();
        }
    }