0

When I call something like:

$class_name = '\App\Models\User';
$class_name::create($attributes);

PhpStorm shows an inspection warning "Method 'create' not found in string".

I don't want to switch off this inspection, as it's very useful in other cases. Is there another way to avoid the warning, using annotations or something else?

2
  • You may help IDE by adding a @var PHPDoc annotation above the variable usage. In this case, it will look like /** @var $class_name \App\Models\User */ Commented Jan 18 at 9:26
  • Perhaps try class-string type from Psalm? psalm.dev/docs/annotating_code/type_syntax/scalar_types/… You need to have that plugin enabled in PhpStorm (it is enabled by default). You do not need the actual Psalm tool.
    – LazyOne
    Commented Jan 18 at 15:25

2 Answers 2

1

The warning you're seeing in PhpStorm is likely due to the fact that PhpStorm is statically analyzing the code, and when you use a string to represent a class name, PhpStorm can't infer the actual class and, therefore, doesn't recognize the methods associated with that class.

To mitigate this, you can use PHPDoc annotations:

/** @var \App\Models\User $class */
$class = '\App\Models\User';

$class::create($attributes);
2
  • That actually works, though I'm getting another problem: as I have the $class as another class property, which I declare as string, it gives a weak warning 'Property type does not match'. This can be solved if I use string|User type, but this would be incorrect to use, as I don't want the User model to be able to pass into this class
    – Yevgeniy
    Commented Jan 18 at 11:41
  • If you want to avoid using string|User type for the property, you can try using the class-string type hint specifically for the property. This indicates that the property should hold a string representing a class name. class YourClass { /** @var class-string */ private $class; } Is that something you are looking for?
    – nequ2k
    Commented Jan 31 at 15:01
0

I've found another way, maybe someone will use it:

call_user_func($class . '::create', $attributes);

Not ideal, but works fine

Not the answer you're looking for? Browse other questions tagged or ask your own question.