9.9 KiB
Rector - Upgrade Your Legacy App to a Modern Codebase
Rector is a reconstructor tool - it does instant upgrades and instant refactoring of your code. Why refactor manually if Rector can handle it for you?
Sponsors
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:
Open-Source First
Rector instantly upgrades and instantly refactors the PHP code of your application. It keeps up to date with the latest PHP changes, and supports many open-source projects:
What Can Rector Do for You?
- 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
- 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.
How to Apply Coding Standards?
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.
Install
composer require rector/rector --dev
If you had conflicts during composer require
or on run, use the Docker image.
Extra Autoloading
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'
Exclude Paths and Rectors
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'
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
You can import FQN class names automatically every time Rector performs a change, so you don't have to do it manually/after each run:
# rector.yaml
parameters:
auto_import_names: true
Running Rector
A. Prepared Sets
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
imports:
- { resource: 'vendor/rector/rector/config/set/code-quality/*.yaml' }
- { resource: 'vendor/rector/rector/config/set/php/php71.yaml' }
- { resource: 'vendor/rector/rector/config/set/php/php72.yaml' }
- { resource: 'vendor/rector/rector/config/set/php/php73.yaml' }
If you use Rector in Docker, you can use absolute path, e.g.
/rector/config/set/php/php71.yaml
B. Custom Sets
-
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
3 Steps to Create Your Own Rector
First, make sure it's not covered by any existing Rectors.
Let's say we want to change method prefixes from set*
to change*
.
$user = new User();
-$user->setPassword('123456');
+$user->changePassword('123456');
1. Create a New Rector and Implement Methods
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;
}
}
2. Register It
# rector.yaml
services:
App\Rector\MyFirstRector: ~
3. Let Rector Refactor Your Code
# see the diff first
vendor/bin/rector process src --dry-run
# if it's ok, apply
vendor/bin/rector process src
That's it!
More Detailed Documentation
How to Contribute
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.
Run Rector in Docker
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 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
Community Packages
Do you use Rector to upgrade your code? Add it here:
- drupal8-rector/drupal8-rector by @mxr576 for Drupal
- [sabbelasichon/typo3-rector](https://github.com/sabbelasichon/typo3-rector] for TYPO3