Updated Rector/ECS YAML to PHP configuration, as current standard. The method order by interface Rector rule is removed now.
Symplify 8 is going to be released in the 2nd half of May. But as in Symfony, you can get ready for future version today.
In the previous post we upgraded Coding Standard from Sniffs to PHPStan. Today we finish with 2nd half - from Fixers to Rector rules.
When you run ECS with version 7.3+:
vendor/bin/ecs check
You might see such notices right before your code gets checked:
PHP Notice: Fixer "..." is deprecated. Use "..." instead
You'll find answer to this question in previous post. To extend answer specifically for this post: Fixer and Rector do the same job - they change code based on specific recipe.
{}()
positions etc.,Now we know why. Let's look how to deal with that.
So what does it mean? Remove all the rules from ecs.php
and let go?
No, all you need to do is switch to Rector rules. It's better working and more reliable since it works with context and not token positions. So at first, you might see new changes in your code.
There are dozen deprecated fixers in total. Let's take it one by one.
First - if you don't have Rector, install it:
composer require rector/rector --dev
The RemoveEmptyDocBlockFixer
rule basically copied behavior of native NoEmptyPhpdocFixer
, so just it instead:
<?php
// ecs.php
declare(strict_types=1);
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
- $services->set(Symplify\CodingStandard\Fixer\Commenting\RemoveEmptyDocBlockFixer::class);
+ $services->set(PhpCsFixer\Fixer\Phpdoc\NoEmptyPhpdocFixer::class);
};
The PregDelimiterFixer
was checking consistent preg delimiter, in this case #
:
class SomeClass
{
public function run()
{
- preg_match('~value~', $value);
+ preg_match('#value#', $value);
}
}
Instead of ~~PhpCsFixer\Fixer\ControlStructure\PregDelimiterFixer
~~ fixer:
↓
use Rector rule:
use Rector\CodingStyle\Rector\FuncCall\ConsistentPregDelimiterRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->set(ConsistentPregDelimiterRector::class)
// default
->arg('delimiter', '#');
};
class SomeClass
{
public function run()
{
- require 'autoload.php';
+ require __DIR__ . '/autoload.php';
}
}
Instead of ~~PhpCsFixer\Fixer\ControlStructure\RequireFollowedByAbsolutePathFixer
~~ fixer,
↓
use Rector rule:
use Rector\CodingStyle\Rector\Include_\FollowRequireByDirRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(FollowRequireByDirRector::class);
};
class SomeClass
{
public function run()
{
try {
// ...
- } catch (SomeException $typoException) {
- $typoException->getMessage();
+ } catch (SomeException $someException) {
+ $someException->getMessage();
}
}
}
Instead of ~~PhpCsFixer\Fixer\Naming\CatchExceptionNameMatchingTypeFixer
~~ Fixer:
↓
use Rector rule:
use Rector\CodingStyle\Rector\Catch_\CatchExceptionNameMatchingTypeRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(CatchExceptionNameMatchingTypeRector::class);
};
class SomeClass
{
/**
* @var EntityManager
*/
- private $eventManager;
+ private $entityManager;
- public function __construct(EntityManager $eventManager)
+ public function __construct(EntityManager $entityManager)
{
- $this->eventManager = $eventManager;
+ $this->entityManager = $entityManager;
}
}
Instead of ~~Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer
~~ Fixer
↓
use Rector rule:
use Rector\Naming\Rector\Class_\RenamePropertyToMatchTypeRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->set(RenamePropertyToMatchTypeRector::class);
};
class SomeClass
{
/**
* @var bool
*/
- private $isDisabled;
+ private $isDisabled = false;
/**
* @var int[]
*/
- private $values;
+ private $values = [];
public function isEmpty()
{
return $this->values === [];
}
}
Instead of:
Symplify\CodingStandard\Fixer\Property\BoolPropertyDefaultValueFixer
~~Symplify\CodingStandard\Fixer\Property\ArrayPropertyDefaultValueFixer
~~↓
use Rector rules:
use Rector\CodingStyle\Rector\Class_\AddArrayDefaultToArrayPropertyRector;
use Rector\SOLID\Rector\Property\AddFalseDefaultToBoolPropertyRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(AddFalseDefaultToBoolPropertyRector::class);
$rectorConfig->rule(AddArrayDefaultToArrayPropertyRector::class);
};
::class
over Strings NamesThis feature is here since PHP 5.5, and it's a massive help for static analysis and instant migrations.
class AnotherClass
{
}
class SomeClass
{
public function run()
{
- return 'AnotherClass';
+ return \AnotherClass::class;
}
}
Instead of ~~Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer
~~ Fixer:
↓
use Rector rule:
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(StringClassNameToClassConstantRector::class);
};
How do you order your methods? Random?
Be sure to read How to Teach Your Team Private Method Sorting in 3 mins.
Instead of:
Symplify\CodingStandard\Fixer\Order\PrivateMethodOrderByUseFixer
~~Symplify\CodingStandard\Fixer\Order\PropertyOrderByComplexityFixer
~~↓
use Rector rules:
use Rector\Order\Rector\Class_\OrderPrivateMethodsByUseRector;
use Rector\Order\Rector\Class_\OrderPropertyByComplexityRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->set(OrderPrivateMethodsByUseRector::class);
$rectorConfig->set(OrderPropertyByComplexityRector::class);
};
*Update: this rule was removed since Rector 0.9+ as not very useful in everyday coding.
final
, if You CanThis will be the biggest added value, as tokens have no idea if your class is extended by another class.
Rector knows that, so be ready for more solid code after you run it.
Instead of ~~Symplify\CodingStandard\Fixer\Solid\FinalInterfaceFixer
~~ Fixer:
↓
use Rector rule:
use Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(FinalizeClassesWithoutChildrenRector::class);
};
And that's it. Now you're ready!
Happy coding!
Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!