On this page
Handling "Unsafe usage of new static()"
This documentation needs review. See "Help improve this page" in the sidebar.
PHPStan warns you of using new static()
in your code when instantiating the current class from within a factory method. This is an extremely common pattern in Drupal core and contributed projects for classes that implement ContainerInjectionInterface
. This allows the classes to be extended and a proper instance instantiated.
Although this is not the best approach In terms of defensive programming, it is needed when writing classes that plan to be extended, or "open by default", as much of the Drupal codebase is expected to be.
Fix the problem
For custom code (code that is not hosted on drupal.org), it is recommended to fix the problem as described in the PHPStan documentation.
In your ContainerInjectionInterface::create
method, do return new self()
instead of return new static()
.
Set the class to final
as well:
final class Foo
{
...
}
Remember, if your class cannot be extended, you limit the backward compatibility promises of your class.
Ignoring the issue
If you choose not to make the class final, add the error to the ignored errors in your configuration. This is what Drupal core has done:
https://git.drupalcode.org/project/drupal/-/blob/10.0.x/core/phpstan.neo...
parameters:
ignoreErrors:
# new static() is a best practice in Drupal, so we cannot fix that.
- "#^Unsafe usage of new static#"
Also add the parameter reportUnmatchedIgnoredErrors: false
to prevent phpstan from warning you that the ignored errors did not occur.
So ultimately your ./phpstan.neon file in your contrib project root might look like this:
includes:
- phar://phpstan.phar/conf/bleedingEdge.neon
parameters:
level: 1
reportUnmatchedIgnoredErrors: false
ignoreErrors:
# new static() is a best practice in Drupal, so we cannot fix that.
- "#^Unsafe usage of new static#"
Additional root causes
For situations unrelated to ContainerInjectionInterface
where you receive the Unsafe usage of new static()
warning, be aware that the PHPStan documentation does provide other alternatives for resolving the warning.
These include:
- Making the constructor
Final
instead of the entire class. - Making the constructor
abstract
. - Enforcing the constructor signature through an interface.
- Using the
@phpstan-consistent-constructor
tag.
Each solution has implications on how your class can be extended, and you should consider each one carefully depending on your particular use case. Making either the class or constructor final will enforce constructor consistency by preventing child classes from overriding the constructor. Marking the constructor Final
will resolve the unsafe usage warning while allowing the rest of the class to be modified by child classes.
Using an abstract constructor or implementing the constructor in an interface will enforce consistency in child classes, resolving the warning. However, classes that extend the original class or implement the interface will need to define their own constructor. This approach allows for more flexibility in child classes at the cost of more boilerplate code. Note: if you run into a rare edge case where enforcing consistency through an interface conflicts with PHPStan generics, consider resolving the warning with any of the other solutions in the section.
Finally, using the PHPStan @phpstan-consistent-constructor
tag in the class comment will both resolve the warning and enforce constructor consistency through static validation with PHPStan. This method relies on using a PHPStan comment instead of native PHP language constructs for consistency enforcement. Using this method also requires PHPStan 1.7
or higher. PHPStan 1.7 is available on the Drupal @core-dev
Composer package as of version 10.0.0-alpha7
or higher.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion