2018-11-11 14:09:23 +01:00
# 4 Steps Create Own Rector
2017-11-18 16:19:47 +01:00
2018-11-11 14:09:23 +01:00
First, make sure your needs is not covered by [any existing Rectors ](/docs/AllRectorsOverview.md ).
2017-11-18 16:19:47 +01:00
2018-11-11 14:09:23 +01:00
Let's say you want to prefix private method call names starting with "internal" with `_` . Not very practical, but it will show the Rector flow.
## 1. New Class
Create class that extends [`Rector\Rector\AbstractRector` ](/src/Rector/AbstractRector.php ). It has many useful methods for checking node type, name, add nodes or remove one. Just run `$this->` and let PHPStorm show you all possible methods.
There 3 methods to implement:
2017-11-18 16:19:47 +01:00
```php
2018-11-11 14:09:23 +01:00
< ?php declare(strict_types=1);
2017-11-18 16:19:47 +01:00
2018-11-11 14:09:23 +01:00
namespace App\Rector;
use PhpParser\Node;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\RectorDefinition;
final class MyFirstRector extends AbstractRector
2017-11-18 16:19:47 +01:00
{
2018-11-11 14:09:23 +01:00
public function getDefinition(): RectorDefinition
{
// what does this do?
// minimalistic before/after sample - to explain in code
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
// what node types we look for?
// String_? FuncCall?
// pick any from https://github.com/nikic/PHP-Parser/tree/master/lib/PhpParser/Node
return [];
}
public function refactor(Node $node): ?Node
{
// what will happen with the node?
// common work flow:
// - should skip? → return null;
// - modify it? → do it, then return $node;
// - remove/add nodes elsewhere? → do it, then return null;
}
2017-11-18 16:19:47 +01:00
}
```
2018-11-11 14:09:23 +01:00
## 2. Add Methods
2017-11-18 16:19:47 +01:00
```php
< ?php declare(strict_types=1);
2018-11-11 14:09:23 +01:00
namespace App\Rector;
2017-11-18 16:19:47 +01:00
2018-11-11 14:09:23 +01:00
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Expr\MethodCall;
2017-11-18 16:19:47 +01:00
use Rector\Rector\AbstractRector;
2018-11-11 14:09:23 +01:00
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
2017-11-18 16:19:47 +01:00
2018-11-11 14:09:23 +01:00
final class MyFirstRector extends AbstractRector
2017-11-18 16:19:47 +01:00
{
2018-11-11 14:09:23 +01:00
public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Add "_" to private method calls that start with "internal"', [
new CodeSample('$this->internalMethod();', '$this->_internalMethod();')
]);
}
/**
* @return string[]
*/
public function getNodeTypes(): array
{
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 "internal*" method names
if (! $this->nameStartsWith($node, 'internal')) {
return null;
}
$node->name = new Identifier('_' . $this->getName($node));
return $node;
}
2017-11-18 16:19:47 +01:00
}
```
2018-11-11 14:09:23 +01:00
## 3. Register it `rector.yml`
```diff
services:
+ App\Rector\MyFirstRector: ~
```
2017-11-18 16:19:47 +01:00
2018-11-11 14:09:23 +01:00
## 4. Let Rector Refactor Your Code
2017-11-18 16:19:47 +01:00
2018-11-11 14:09:23 +01:00
```bash
vendor/bin/rector process src --dry-run
# apply it
vendor/bin/rector process src
```
If you use `rector.yml` from another directory or another name, set it with `--config` option:
```bash
vendor/bin/rector process src --config ../custom-rector.yml
```
2017-11-18 16:19:47 +01:00
2018-11-11 14:09:23 +01:00
That's it!