rectorphp / rector

Instant Upgrades and Automated Refactoring of any PHP 5.3+ code
https://getrector.com
MIT License
8.71k stars 686 forks source link

[Php80] ClassPropertyAssignToConstructorPromotionRector can break Symfony auto-wiring #7268

Closed kick-the-bucket closed 2 years ago

kick-the-bucket commented 2 years ago

Bug Report

Subject Details
Rector version v0.13.6

When promoting constructor properties and there is a name miss-match between the property name and constructor argument name - the property name is used. This leads to problems, when there are more than one instance of the class available and named aliases are used (the class to auto-wire in selected by constructor argument name). So if the argument was auto-wired by name and this name is changed - it either can no longer be auto-wired or it can be auto-wired to a different (usually default instead of specific one referenced by the argument name) instance and break intended behavior.

Minimal PHP Code Causing Issue

Example borrowed from How to Log Messages to different Files

With monolog config

monolog:
    channels:
        - foo

this is auto-wired the LoggerInterface instance for the foo channel.

class Service
{
    private LoggerInterface $logger;

    public function construct(LoggerInterface $fooLogger)
    {
        $this->logger = $fooLogger;
    }
}

Currently it will be refactored by ClassPropertyAssignToConstructorPromotionRector to

class Service
{
    public function construct(private LoggerInterface $logger)
    {
    }
}

which will be auto-wired to a different LoggerInterface instance for the app channel.

Expected Behaviour

There are quire some options how to dealt with this:

TomasVotruba commented 2 years ago

It seems that keeping $fooLogger name would be the best way to go. Then rename the property fetches accordingly

TomasVotruba commented 2 years ago

Closing as not an issue and suggestion is accepted, to keep focus on relevant and opened issues.

On the other hand, renaming properties can be dangerous and lead to another unexpected consequences. In this case, I'd recommend to handle Rector the 1:1 type rename the constructor params. Then update the configs to match the new names and types. That way you can also fix missnames of property names.

The best solution IMO is not to use named arguments at all and go for type-based autowiring or positions. That way you remove this issue completelly from your project :+1:

Geolim4 commented 1 year ago

Hello,

Sorry to bump this @TomasVotruba, but I'm unable to find out how to disable constructor argument renaming using rule configuration ?