2019-10-25 00:59:42 +00:00
# Rector - Upgrade Your Legacy App to a Modern Codebase
2017-07-15 17:20:20 +00:00
2018-09-11 18:46:11 +00:00
Rector is a **rec**onstruc**tor** tool - it does **instant upgrades** and **instant refactoring** of your code.
2019-10-25 17:38:41 +00:00
Why refactor manually if Rector can handle 80% for you?
2018-02-02 16:51:41 +00:00
2017-11-13 01:58:21 +00:00
[![Build Status ](https://img.shields.io/travis/rectorphp/rector/master.svg?style=flat-square )](https://travis-ci.org/rectorphp/rector)
2018-11-09 13:45:14 +00:00
[![Coverage Status ](https://img.shields.io/coveralls/rectorphp/rector/master.svg?style=flat-square )](https://coveralls.io/github/rectorphp/rector?branch=master)
2018-07-02 13:02:27 +00:00
[![Downloads ](https://img.shields.io/packagist/dt/rector/rector.svg?style=flat-square )](https://packagist.org/packages/rector/rector)
2017-07-15 17:20:20 +00:00
2018-10-28 17:02:30 +00:00
2019-10-19 10:42:36 +00:00
![Rector-showcase ](docs/images/rector-showcase-var.gif )
2018-01-13 15:01:31 +00:00
2019-04-29 21:42:11 +00:00
< br >
## Sponsors
Rector grows faster with your help, the more you help the more work it saves you.
2019-09-03 22:50:44 +00:00
Check out [Rector's Patreon ](https://www.patreon.com/rectorphp ). One-time donation is welcomed [through PayPal ](https://www.paypal.me/rectorphp ).
2019-04-29 21:42:11 +00:00
2019-08-19 13:49:41 +00:00
Thank you:
2019-08-19 13:50:06 +00:00
< a href = "https://spaceflow.io/en" > < img src = "/docs/images/spaceflow.png" > < / a >
2019-08-19 13:49:41 +00:00
2019-04-29 21:42:11 +00:00
< br >
## Open-Source First
2019-10-25 17:38:41 +00:00
Rector **instantly upgrades and instantly refactors the PHP code of your application** . It supports all modern versions of PHP and many open-source projects:
2017-07-15 17:20:20 +00:00
2018-10-21 09:00:39 +00:00
< br >
2017-10-30 15:00:28 +00:00
< p align = "center" >
2019-06-08 20:41:52 +00:00
< a href = "/config/set/php" > < img src = "/docs/images/php.png" > < / a >
2019-10-20 14:46:52 +00:00
< img src = "/docs/images/space.png" width = 40 >
2019-06-08 20:41:52 +00:00
< a href = "/config/set/symfony" > < img src = "/docs/images/symfony.png" > < / a >
2019-10-20 14:46:52 +00:00
< img src = "/docs/images/space.png" width = 40 >
2019-10-20 14:47:40 +00:00
< a href = "/config/set/laravel" > < img src = "/docs/images/laravel.png" > < / a >
< br >
< a href = "/config/set/cakephp" > < img src = "/docs/images/cakephp.png" > < / a >
< img src = "/docs/images/space.png" width = 40 >
2019-11-04 00:48:08 +00:00
< a href = "/config/set/phpunit" > < img src = "/docs/images/phpunit.png" > < / a >
2019-10-20 14:46:52 +00:00
< img src = "/docs/images/space.png" width = 40 >
2019-06-08 20:41:52 +00:00
< a href = "/config/set/twig" > < img src = "/docs/images/twig.png" > < / a >
2017-10-30 15:00:28 +00:00
< / p >
2017-08-20 15:40:19 +00:00
2018-10-21 09:00:39 +00:00
< br >
2019-10-25 00:59:42 +00:00
## What Can Rector Do for You?
2018-08-01 20:29:01 +00:00
2019-04-29 21:42:11 +00:00
- Rename classes, methods, properties, namespaces or constants
- Complete [parameter, var or return type declarations ](https://www.tomasvotruba.cz/blog/2019/01/03/how-to-complete-type-declarations-without-docblocks-with-rector/ ) 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 ](https://www.tomasvotruba.cz/blog/2019/02/21/how-we-migrated-from-nette-to-symfony-in-3-weeks-part-1/ )
2019-03-09 13:23:11 +00:00
- [Complete PHP 7.4 property type declarations ](https://www.tomasvotruba.cz/blog/2018/11/15/how-to-get-php-74-typed-properties-to-your-code-in-few-seconds/ )
2019-10-25 00:59:42 +00:00
- [Refactor Laravel facades to dependency injection ](https://www.tomasvotruba.cz/blog/2019/03/04/how-to-turn-laravel-from-static-to-dependency-injection-in-one-day/ )
2017-12-28 19:58:35 +00:00
- And much more...
2017-07-15 17:20:20 +00:00
2019-09-03 22:50:44 +00:00
...**look at the overview of [all available Rectors ](/docs/AllRectorsOverview.md )** with before/after diffs and configuration examples. You can use them to build your own sets.
2018-04-29 09:03:47 +00:00
2019-07-09 15:05:10 +00:00
## How to Apply Coding Standards?
2019-10-25 00:59:42 +00:00
The AST libraries that Rector uses aren't well-suited for coding standards, so it's better to let coding standard tools do that.
2019-07-09 16:17:03 +00:00
2019-10-25 00:59:42 +00:00
Don't have a coding standard tool for your project? Consider adding [EasyCodingStandard ](https://github.com/Symplify/EasyCodingStandard ), [PHP CS Fixer ](https://github.com/FriendsOfPHP/PHP-CS-Fixer ) or [PHP_CodeSniffer ](https://github.com/squizlabs/PHP_CodeSniffer ).
2019-07-09 15:05:10 +00:00
2017-07-15 17:20:20 +00:00
## Install
```bash
2018-10-06 17:28:57 +00:00
composer require rector/rector --dev
2017-07-15 17:20:20 +00:00
```
2019-10-26 01:11:11 +00:00
**Did you have conflicts during `composer require` or on run?**
- Use the [Docker image ](#run-rector-in-docker )
2018-01-06 15:50:22 +00:00
2018-02-08 14:25:45 +00:00
### Extra Autoloading
2019-09-03 22:50:44 +00:00
Rector relies on project and autoloading of its classes. To specify your own autoload file, use `--autoload-file` option:
2018-02-09 00:16:54 +00:00
2018-02-08 14:25:45 +00:00
```bash
2018-02-08 14:27:14 +00:00
vendor/bin/rector process ../project --autoload-file ../project/vendor/autoload.php
2018-02-08 14:25:45 +00:00
```
2019-10-25 00:59:42 +00:00
Or use a `rector.yaml` config file:
2018-04-13 19:14:07 +00:00
```yaml
2019-02-03 17:46:45 +00:00
# rector.yaml
2018-04-13 19:14:07 +00:00
parameters:
2018-09-26 07:03:04 +00:00
autoload_paths:
2018-11-09 13:58:49 +00:00
- 'vendor/squizlabs/php_codesniffer/autoload.php'
- 'vendor/project-without-composer'
2018-04-13 19:14:07 +00:00
```
2019-11-08 12:08:42 +00:00
### Exclude Paths and Rectors
2019-01-18 11:41:07 +00:00
2018-11-09 13:58:49 +00:00
You can also **exclude files or directories** (with regex or [fnmatch ](http://php.net/manual/en/function.fnmatch.php )):
2018-08-29 20:45:09 +00:00
```yaml
2019-02-03 17:46:45 +00:00
# rector.yaml
2018-08-29 20:45:09 +00:00
parameters:
exclude_paths:
- '*/src/*/Tests/*'
```
2019-10-25 00:59:42 +00:00
You can use a whole ruleset, except one rule:
2019-01-18 11:41:07 +00:00
```yaml
2019-02-03 17:46:45 +00:00
# rector.yaml
2019-01-18 11:41:07 +00:00
parameters:
exclude_rectors:
- 'Rector\CodeQuality\Rector\If_\SimplifyIfReturnBoolRector'
```
2019-11-08 12:08:42 +00:00
### Provide PHP Version
2019-10-25 00:59:42 +00:00
By default Rector uses the language features matching your system version of PHP. You can configure it for a different PHP version:
2019-02-23 13:03:07 +00:00
```yaml
2019-10-12 15:51:07 +00:00
# rector.yaml
2019-02-23 13:03:07 +00:00
parameters:
2019-10-25 00:59:42 +00:00
php_version_features: '7.2' # your version is 7.3
2019-02-23 13:03:07 +00:00
```
2019-11-08 12:08:42 +00:00
### Import Use Statements
2019-11-04 23:25:44 +00:00
FQN classes are imported by default every time Rector performs a change, so you don't have to do it manually/after each run. You can disable it by:
2019-10-12 15:51:07 +00:00
```yaml
# rector.yaml
parameters:
2019-11-04 23:25:44 +00:00
auto_import_names: false
2019-10-12 15:51:07 +00:00
```
2018-11-09 13:58:49 +00:00
## Running Rector
2017-10-30 13:33:09 +00:00
### A. Prepared Sets
2019-10-25 00:59:42 +00:00
Featured open-source projects have **prepared sets** . You can find them in [`/config/set` ](/config/set ) or by running:
2017-10-30 13:33:09 +00:00
2018-11-09 13:58:49 +00:00
```bash
2019-08-25 10:19:03 +00:00
vendor/bin/rector sets
2018-11-09 13:58:49 +00:00
```
2017-12-28 19:58:35 +00:00
2019-09-03 22:50:44 +00:00
Let's say you pick the `symfony40` set and you want to upgrade your `/src` directory:
2017-09-23 21:51:04 +00:00
2018-11-09 13:58:49 +00:00
```bash
2019-10-25 00:59:42 +00:00
# show a list of known changes in Symfony 4.0
2019-08-25 10:19:03 +00:00
vendor/bin/rector process src --set symfony40 --dry-run
2018-11-09 13:58:49 +00:00
```
2018-08-30 08:50:03 +00:00
2018-11-09 13:58:49 +00:00
```bash
2019-10-25 00:59:42 +00:00
# apply upgrades to your code
2019-08-25 10:19:03 +00:00
vendor/bin/rector process src --set symfony40
2018-11-09 13:58:49 +00:00
```
2018-08-30 08:50:03 +00:00
2019-10-17 14:38:26 +00:00
Some sets, such as [`code-quality` ](/config/set/code-quality ) can be
used on a regular basis. You can include them in your `rector.yaml` to
run them by default:
```yaml
# rector.yaml
imports:
2019-11-05 11:25:19 +00:00
- { resource: 'vendor/rector/rector/config/set/code-quality/code-quality.yaml' }
2019-10-17 14:38:26 +00:00
- { 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`
2017-10-30 13:33:09 +00:00
### B. Custom Sets
2017-09-27 21:58:14 +00:00
2019-10-25 00:59:42 +00:00
1. Create a `rector.yaml` config file with your desired Rectors:
2017-09-27 21:58:14 +00:00
2018-11-09 13:58:49 +00:00
```yaml
2018-03-03 20:08:25 +00:00
services:
2018-11-09 13:58:49 +00:00
Rector\Rector\Architecture\DependencyInjection\AnnotatedPropertyInjectToConstructorInjectionRector:
$annotation: "inject"
2017-12-20 01:39:06 +00:00
```
2017-09-27 21:58:14 +00:00
2019-10-25 00:59:42 +00:00
2. Run Rector on your `/src` directory:
2017-07-15 17:20:20 +00:00
2017-12-20 01:39:06 +00:00
```bash
vendor/bin/rector process src --dry-run
2018-11-09 13:58:49 +00:00
# apply
2017-12-20 01:39:06 +00:00
vendor/bin/rector process src
```
2017-07-15 17:20:20 +00:00
2019-10-25 00:59:42 +00:00
## 3 Steps to Create Your Own Rector
2019-02-07 12:52:15 +00:00
2019-10-25 00:59:42 +00:00
First, make sure it's not covered by [any existing Rectors ](/docs/AllRectorsOverview.md ).
2019-02-07 12:52:15 +00:00
2019-10-26 01:11:11 +00:00
Let's say we want to **change method calls from `set*` to `change*`** .
2019-02-07 12:52:15 +00:00
```diff
$user = new User();
-$user->setPassword('123456');
+$user->changePassword('123456');
```
2019-10-25 00:59:42 +00:00
### 1. Create a New Rector and Implement Methods
2019-02-07 12:52:15 +00:00
2019-10-25 00:59:42 +00:00
Create a class that extends [`Rector\Rector\AbstractRector` ](/src/Rector/AbstractRector.php ). 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.
2019-02-07 12:52:15 +00:00
```php
2019-10-13 05:59:52 +00:00
< ?php
declare(strict_types=1);
2019-02-07 12:52:15 +00:00
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
{
2019-05-03 13:48:22 +00:00
// what does this do?
// minimalistic before/after sample - to explain in code
2019-03-29 09:27:11 +00:00
return new RectorDefinition('Change method calls from set* to change*.', [
2019-05-03 13:48:22 +00:00
new CodeSample('$user->setPassword("123456");', '$user->changePassword("123456");')
2019-02-07 12:52:15 +00:00
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
2019-05-03 13:48:22 +00:00
// what node types we look for?
// pick any node from https://github.com/rectorphp/rector/blob/master/docs/NodesOverview.md
2019-02-07 12:52:15 +00:00
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
{
2019-03-29 09:27:11 +00:00
// we only care about "set*" method names
2019-05-03 13:51:39 +00:00
if (! $this->isName($node, 'set*')) {
// return null to skip it
2019-02-07 12:52:15 +00:00
return null;
}
2019-05-03 13:51:39 +00:00
$methodCallName = $this->getName($node);
2019-02-07 12:52:15 +00:00
$newMethodCallName = Strings::replace($methodCallName, '#^set#', 'change');
$node->name = new Identifier($newMethodCallName);
2019-05-03 13:51:39 +00:00
// return $node if you modified it
2019-02-07 12:52:15 +00:00
return $node;
}
}
```
2019-10-25 00:59:42 +00:00
### 2. Register It
2019-02-07 12:52:15 +00:00
```yaml
# rector.yaml
services:
App\Rector\MyFirstRector: ~
```
2019-05-03 13:48:22 +00:00
### 3. Let Rector Refactor Your Code
2019-02-07 12:52:15 +00:00
```bash
# see the diff first
vendor/bin/rector process src --dry-run
# if it's ok, apply
vendor/bin/rector process src
```
That's it!
2017-12-28 19:58:35 +00:00
## More Detailed Documentation
2017-10-15 09:07:53 +00:00
2019-10-25 00:59:42 +00:00
- **[All Rectors: Overview](/docs/AllRectorsOverview.md)**
- [How Does Rector Work? ](/docs/HowItWorks.md )
2019-10-26 01:11:11 +00:00
- [Nodes Overview ](/docs/NodesOverview.md )
2017-10-15 09:07:53 +00:00
2017-12-28 19:58:35 +00:00
## How to Contribute
2017-07-15 17:20:20 +00:00
Just follow 3 rules:
- **1 feature per pull-request**
2019-09-03 22:50:44 +00:00
- **New features need tests**
2017-12-28 20:37:43 +00:00
- Tests, coding standards and PHPStan **checks must pass** :
2017-07-15 17:20:20 +00:00
```bash
2017-12-28 20:27:16 +00:00
composer complete-check
2017-07-15 17:20:20 +00:00
```
2019-09-03 22:50:44 +00:00
Do you need to fix coding standards? Run:
2017-07-15 17:20:20 +00:00
```bash
2017-08-21 10:12:51 +00:00
composer fix-cs
2017-07-15 17:20:20 +00:00
```
2019-10-25 00:59:42 +00:00
We would be happy to accept PRs that follow these guidelines.
2018-12-12 09:02:10 +00:00
2018-12-31 19:27:38 +00:00
## Run Rector in Docker
2019-10-25 00:59:42 +00:00
You can run Rector on your project using Docker:
2018-12-31 19:27:38 +00:00
2018-12-12 09:02:10 +00:00
```bash
2019-08-25 10:19:03 +00:00
docker run -v $(pwd):/project rector/rector:latest process /project/src --set symfony40 --dry-run
2019-03-11 14:12:27 +00:00
2019-10-26 01:11:11 +00:00
# Note that a volume is mounted from `pwd` (the current directory) into `/project` which can be accessed later.
2018-12-11 17:22:54 +00:00
```
2019-03-11 14:27:13 +00:00
Using `rector.yaml` :
```bash
2019-03-11 14:44:39 +00:00
docker run -v $(pwd):/project rector/rector:latest process /project/app --config /project/rector.yaml --autoload-file /project/vendor/autoload.php --dry-run
2019-03-11 14:27:13 +00:00
```
2019-04-02 13:40:53 +00:00
### Community Packages
2019-10-25 00:59:42 +00:00
Do you use Rector to upgrade your code? Add it here:
2019-04-02 13:40:53 +00:00
2019-10-18 18:54:54 +00:00
- [drupal8-rector/drupal8-rector ](https://github.com/drupal8-rector/drupal8-rector ) by [@mxr576 ](https://github.com/mxr576 ) for [Drupal ](https://www.drupal.org/ )
2019-10-25 01:04:18 +00:00
- [sabbelasichon/typo3-rector ](https://github.com/sabbelasichon/typo3-rector ) for [TYPO3 ](https://typo3.org/ )