Do you want more PHPStan violations?

Edit 2019–07–08: Good news! PHPStan 0.11.10 includes support for inferring private property type from constructor! https://github.com/phpstan/phpstan/releases/tag/0.11.10:

Turn on with inferPrivatePropertyTypeFromConstructor: true


We use PHPStan a lot and we love it. Some of us even donate each month some money via Patreon.

I faced an issue few months ago, and I hit the very same one today while I started a big refactoring of an application. And I totally forgot about it 😂 Memory sucks :)

So let’s talk about it, and see how to solve it. And now I hope I will remember to fix it on every project I’m working on.

Consider this piece of code:

class Model
{
}

class ServiceA
{
    private $serviceB;

    public function __construct(ServiceB $serviceB)
    {
        $this->serviceB = $serviceB;
    }

    public function init()
    {
        // This line will generate a FatalError (DateTime != Model)
        $this->serviceB->process(new DateTime());
    }
}

class ServiceB
{
    public function process(Model $model)
    {
    }
}

I’m expecting to get this error:

Parameter #1 $model of method ServiceB::process() expects Model, DateTime given.

But why is it valid? Because PHPStan does not infer type from constructor argument. And this is totally valid to not do so.

A solution would be to add some PHPDoc:

class ServiceA
{
    /** @var ServiceB */
    private $serviceB;
}

In the Symfony community, we have some standards. Additionally, I hate useless PHPDoc. I don’t want to pollute my code by adding them everywhere.

Symfony’s coding standards state to not add the PHPDoc to a property if it can be inferred from the constructor, it is also the default configuration of PHP CS Fixer and it is considered a best practice by some.

Since PHPStan has a nice plugin system, I wrote a plugin to automatically add theses type-hint in PHPStan engine few months ago. I used it in my current application and I was able to find 45 new violations \o/

You can read the code and add it to your project if you want to.


blog comments powered by Disqus