Rector is a reconstructor tool - it does instant upgrades and instant refactoring of your code. Why refactor manually if Rector can handle 80% of the task 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 donations are welcome 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
.
No time to try Rector locally?
We have an online demo just for you!
composer require rector/rector --dev
Having conflicts during composer require
or on run?
- Use the Rector Prefixed
Using a different PHP version than Rector supports?
- Use the Docker image
Try the demo and get familiar with rector
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
configuration file with your desired Rectors or provide another configuration file with--config
:services: Rector\Core\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 whatever autoload setup the project it is fixing is using by using the Composer autoloader as default. 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
configuration 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);
}
}
If you have a configuration file for Rector including many sets and Rectors, you might want at times to run only a single Rector from them. The --only
argument allows that, for example :
vendor/bin/rector process --set solid --only "Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector" src/
Will only run Rector\SOLID\Rector\Class_\FinalizeClassesWithoutChildrenRector
.
Please note that the backslash in the Rector's fully-qualified class name needs to be properly escaped (by surrounding the string in double quotes).
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 want to 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\Core\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 Utils\Rector;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Expr\MethodCall;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
final class MyFirstRector extends AbstractRector
{
/**
* @return string[]
*/
public function getNodeTypes(): array
{
// what node types are we looking 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->name, '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;
}
/**
* From this method documentation is generated.
*/
public function getDefinition(): RectorDefinition
{
return new RectorDefinition(
'Change method calls from set* to change*.', [
new CodeSample(
// code before
'$user->setPassword("123456");',
// code after
'$user->changePassword("123456");'
),
]
);
}
}
This is how the file structure should look like:
/src/YourCode.php
/utils/Rector/MyFirstRector.php
rector.yaml
composer.json
We also need to load Rector rules in composer.json
:
{
"autoload": {
"psr-4": {
"App\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Utils\\": "utils"
}
}
}
After adding this to composer.json
, be sure to reload Composer's class map:
composer dump-autoload
# rector.yaml
services:
Utils\Rector\MyFirstRector: ~
The rector.yaml
configuration is loaded by default, so we can skip it.
# see the diff first
vendor/bin/rector process src --dry-run
# if it's ok, apply
vendor/bin/rector process src
That's it!
Do you want to save time with making rules and tests?
Use the create
command.
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: