Rector is a reconstructor tool - it does instant upgrades and instant refactoring of your code. Why refactor manually if Rector can handle 80% for you?
Rector grows faster with your help, the more you help the more work it saves you. Check out Rector's Patreon. One-time donation is welcomed through PayPal.
Thank you:
Rector instantly upgrades and instantly refactors the PHP code of your application. It supports all modern versions of PHP and many open-source projects:
- Rename classes, methods, properties, namespaces or constants
- Complete parameter, var or return type declarations based on static analysis of your code
- Upgrade your code from PHP 5.3 to PHP 7.4
- Migrate your project from Nette to Symfony
- Complete PHP 7.4 property type declarations
- Refactor Laravel facades to dependency injection
- Prepare a codebase before huge upgrades
- Get rid of technical debt
- And much more...
...look at the overview of all available Rectors with before/after diffs and configuration examples. You can use them to build your own sets.
The AST libraries that Rector uses aren't well-suited for coding standards, so it's better to let coding standard tools do that.
Don't have a coding standard tool for your project? Consider adding EasyCodingStandard, PHP CS Fixer or PHP_CodeSniffer.
Tip: If you have EasyCodingStandard, you can start your set with ecs-after-rector.yaml
.
composer require rector/rector --dev
Do you have conflicts during composer require
or on run?
- Use the Rector Prefixed
Do you need different PHP version than Rector supports?
- Use the Docker image
Featured open-source projects have prepared sets. You can find them in /config/set
or by running:
vendor/bin/rector sets
Let's say you pick the symfony40
set and you want to upgrade your /src
directory:
# show a list of known changes in Symfony 4.0
vendor/bin/rector process src --set symfony40 --dry-run
# apply upgrades to your code
vendor/bin/rector process src --set symfony40
Some sets, such as code-quality
can be
used on a regular basis. You can include them in your rector.yaml
to
run them by default:
# rector.yaml
parameters:
sets:
- 'code-quality'
- 'php71'
- 'php72'
- 'php73'
-
Create a
rector.yaml
config file with your desired Rectors:services: Rector\Rector\Architecture\DependencyInjection\AnnotatedPropertyInjectToConstructorInjectionRector: $annotation: "inject"
-
Run Rector on your
/src
directory:vendor/bin/rector process src --dry-run # apply vendor/bin/rector process src
Rector relies on project and autoloading of its classes. To specify your own autoload file, use --autoload-file
option:
vendor/bin/rector process ../project --autoload-file ../project/vendor/autoload.php
Or use a rector.yaml
config file:
# rector.yaml
parameters:
autoload_paths:
- 'vendor/squizlabs/php_codesniffer/autoload.php'
- 'vendor/project-without-composer'
You can also exclude files or directories (with regex or fnmatch):
# rector.yaml
parameters:
exclude_paths:
- '*/src/*/Tests/*'
You can use a whole ruleset, except one rule:
# rector.yaml
parameters:
exclude_rectors:
- 'Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector'
Do you want to skip just specific line with specific rule?
Use @noRector \FQN name
annotation:
class SomeClass
{
/**
* @noRector \Rector\DeadCode\Rector\ClassMethod\RemoveEmptyClassMethodRector
*/
public function foo()
{
/** @noRector \Rector\DeadCode\Rector\Plus\RemoveDeadZeroAndOneOperationRector */
round(1 + 0);
}
}
By default Rector uses the language features matching your system version of PHP. You can configure it for a different PHP version:
# rector.yaml
parameters:
php_version_features: '7.2' # your version is 7.3
If you're annoyed by repeating paths in arguments, you can move them to config instead:
# rector.yaml
parameters:
paths:
- 'src'
- 'tests'
FQN classes are not imported by default. If you don't to do do it manually after every Rector run, enable it by:
# rector.yaml
parameters:
auto_import_names: true
You can also fine-tune how these imports are processed:
# rector.yaml
parameters:
# this will not import root namespace classes, like \DateTime or \Exception
import_short_classes: false
# this will not import classes used in PHP DocBlocks, like in /** @var \Some\Class */
import_doc_blocks: false
Execution can be limited to changed files using the process
option --match-git-diff
.
This option will filter the files included by the configuration, creating an intersection with the files listed in git diff
.
vendor/bin/rector process src --match-git-diff
This option is useful in CI with pull-requests that only change few files.
To work with some Symfony rules, you now need to link your container XML file
# rector.yaml
parameters:
# path to load services from
symfony_container_xml_path: 'var/cache/dev/AppKernelDevDebugContainer.xml'
First, make sure it's not covered by any existing Rectors.
Let's say we want to change method calls from set*
to change*
.
$user = new User();
-$user->setPassword('123456');
+$user->changePassword('123456');
Create a class that extends Rector\Rector\AbstractRector
. It will inherit useful methods e.g. to check node type and name. See the source (or type $this->
in an IDE) for a list of available methods.
<?php
declare(strict_types=1);
namespace App\Rector;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Expr\MethodCall;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
final class MyFirstRector extends AbstractRector
{
public function getDefinition(): RectorDefinition
{
// what does this do?
// minimalistic before/after sample - to explain in code
return new RectorDefinition('Change method calls from set* to change*.', [
new CodeSample('$user->setPassword("123456");', '$user->changePassword("123456");')
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
// what node types we look for?
// pick any node from https://github.com/rectorphp/rector/blob/master/docs/NodesOverview.md
return [MethodCall::class];
}
/**
* @param MethodCall $node - we can add "MethodCall" type here, because only this node is in "getNodeTypes()"
*/
public function refactor(Node $node): ?Node
{
// we only care about "set*" method names
if (! $this->isName($node, 'set*')) {
// return null to skip it
return null;
}
$methodCallName = $this->getName($node);
$newMethodCallName = Strings::replace($methodCallName, '#^set#', 'change');
$node->name = new Identifier($newMethodCallName);
// return $node if you modified it
return $node;
}
}
# rector.yaml
services:
App\Rector\MyFirstRector: ~
# see the diff first
vendor/bin/rector process src --dry-run
# if it's ok, apply
vendor/bin/rector process src
That's it!
Just follow 3 rules:
-
1 feature per pull-request
-
New features need tests
-
Tests, coding standards and PHPStan checks must pass:
composer complete-check
Do you need to fix coding standards? Run:
composer fix-cs
We would be happy to accept PRs that follow these guidelines.
You can run Rector on your project using Docker:
docker run -v $(pwd):/project rector/rector:latest process /project/src --set symfony40 --dry-run
# Note that a volume is mounted from `pwd` (the current directory) into `/project` which can be accessed later.
Using rector.yaml
:
docker run -v $(pwd):/project rector/rector:latest process /project/app --config /project/rector.yaml --autoload-file /project/vendor/autoload.php --dry-run
Do you use Rector to upgrade your code? Add it here: