Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Rector + PHPStan conflict in rules

I migrated project from PHP 7.4 to 8.3.

I have left with 1 error in rector that I am not able to solve.

  •    $namesArray = explode($separator, $names);
    
  •    $namesArray = explode($separator, (string) $names);
    

end diff ----------- Applied rules: NullToStrictStringFuncCallArgRector

I have a trait that has method

public function getMultipleNamesImport(int $productId, string $separator = ',', string $names = ''): array
    {
        if ($this->checkProductIdExists($productId))
        {
            return [];
        }

        if (empty($names))
        {
            $names = $this->getNamesByProductId($productId);
        }

        $names = explode($separator, $names);

So $names as a parametr is always string.

Only option where it can change is here

if (empty($names))
{
    $names = $this->getNamesByProductId($productId);
}

But it always returns a string too. In a trait it is as a abstract function.

abstract protected function getNamesByProductId(int $productId): string;

And each implementation also has string as a return type.

Problem is when I use rector rule phpstan throws plenty errors in each use, that I try to convert string to string. is this a bug in rector?

I have newest version of rector/rector 2.1.7 and phpstan/phpstan 2.1.29., phpstan/phpstan-nette 2.0.6, phpstan/phpdoc-parser 2.3.0, phpstan/phpstan-strict-rules 2.0.7

I tried to accept rector proposal but phpstan then reports errors.

like image 400
tttpapi Avatar asked May 25 '26 15:05

tttpapi


1 Answers

This isn’t actually a PHP bug, it’s just Rector being too aggressive.

What happens:

  • Rector sees explode($separator, $names) and assumes $names could be null.

  • It rewrites it into explode($separator, (string) $names) to be “safe.”

  • But in my case, $names is always a string: it has a default '', the abstract method is typed string, and all implementations return string.

So the (string) cast is redundant. PHPStan is right to complain, because I’m “casting a string to a string.”

This is basically a false-positive from NullToStrictStringFuncCallArgRector.

  1. Disable that Rector rule in rector.php:

    $rectorConfig->skip([
        Rector\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector::class,
    ]);
    
    

    or annotate just the line with:

    // @noRector Rector\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector
    
    
  2. Add explicit phpdoc for the param (@param string $names) – sometimes Rector respects that and stops casting.

The simplest fix was just to skip this Rector rule. The code is already type-safe and PHPStan validates it correctly.

like image 165
zazz Avatar answered May 27 '26 03:05

zazz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!