Open-source project
rectorphp/rector avatar
rectorphp/rector

Rector: dry-run shows the diff, then a coding standard tool fixes the formatting

Instant Upgrades and Automated Refactoring of any PHP 5.3+ code

10,508 stars743 forksPHPMIT

At a glance

What is it?
Rector rewrites PHP source through an abstract syntax tree rather than through text substitution, which is what makes it capable of real upgrades from PHP 5.3 through 8.5 and of framework migrations. The cost of that design is stated plainly in its own drawbacks list: the output is poorly formatted, files that mix PHP and HTML need manual verification afterwards, and you are expected to run a second tool to make the result readable.
Who is it for?
Adopt Rector when you have a large legacy codebase pinned to an old PHP or framework version and a test suite that can prove the rewrite did not break behaviour, because that safety net is what makes an automated migration acceptable. Do not point it at template files or any PHP and HTML mixture without reading the diff afterwards, and pair it with a coding standard tool from day one.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • rectorphp/rector10,508 ★ · +81
Star history
Repository2026-09-222026-11-14
rectorphp/rector10.4k10.5k

81 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The repository ships a vendor directory, and the source lives in rector-src

The root of this repository explains a lot about how the tool is distributed. There is a vendor/ directory committed alongside src/, bin/, config/, rules/, bootstrap.php, preload.php, templates/, stubs-rector/ and an e2e/ directory, and the contributing section points readers to CONTRIBUTING.md and then to a different repository, rector/rector-src, for development. In other words, what you clone here is a built and vendored distribution, and the place where changes are authored is elsewhere. That has two consequences. First, if you are auditing the code to understand how a rule behaves, you are reading a bundled artifact rather than the development tree. Second, if you want to contribute a rule, the contributing guide is the correct starting point and rector-src is where the work happens. There is also an UPGRADING.md at the root, which is the file to read when a new Rector release changes something you depend on, and the rule sets that matter to a large application are not in this repository at all: Symfony, PHPUnit and Doctrine support live in separate extension repositories, and the framework coverage comes from there.

One rule or a set, and the difference is written in rector.php

Rector has two ways to be used, and the documentation frames them as a choice about control. You can register a single rule, which keeps the change under control, or you can apply a group of rules called sets, which applies many changes at once. The decision lives in a rector.php file you create in your project root, and it is a fluent builder rather than an array of configuration keys:

php
use Rector\Config\RectorConfig;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector;

return RectorConfig::configure()
    // register single rule
    ->withRules([
        TypedPropertyFromStrictConstructorRector::class
    ])
    // here we can define, what prepared sets of rules will be applied
    ->withPreparedSets(
        deadCode: true,
        codeQuality: true
    );

Two methods appear in that example and they are the whole configuration vocabulary worth knowing up front. withRules takes the rule classes you want, one at a time. withPreparedSets takes named arguments, here deadCode and codeQuality switched on, which is how a bundle of prepared rules is opted into. The example uses both, which tells you something important about how the two interact: you can adopt a broad baseline and then layer specific rules on top. The full documentation lives at getrector.com/documentation, and there is a separate rule browser at getrector.com/find-rule, which is where you look up an individual transformation by name before committing to it.

--dry-run is the difference between a review and an edit

This is the operational point that matters most for an automated tool, and it is handled well. To see what Rector would do without touching a file:

bash
vendor/bin/rector src --dry-run

Rector shows you a diff of the files it would change. To actually apply the changes, drop the flag:

bash
vendor/bin/rector src

Rector is installed as a development dependency rather than a runtime one, so the install is scoped correctly:

bash
composer require rector/rector --dev

That combination, a dev-only dependency, a diff-first command, and a configuration file you can narrow rule by rule, is what makes a large refactoring reviewable rather than a leap of faith. It also means the migration is incremental by design: start with one rule on one directory, read the diff, and widen. The limit of that safety is worth stating plainly. The diff tells you what changed, not whether the program still behaves correctly, so the real gate is a test suite that runs against the rewritten code. Rector cannot verify behaviour for you, and with a dead-code set enabled you are asking it to delete code on the strength of static analysis alone.

AST output knows nothing about spaces, so a second tool is required

The first entry under known drawbacks explains why Rector's output looks wrong before you have done anything wrong with it. Rector uses nikic/php-parser, which is built on a technology called an abstract syntax tree, and an AST does not know about spaces. When that tree is written back to a file, the result is poorly formatted code, and the same is true of docblock annotations. This is not a bug to be filed; it is a consequence of the representation. The consequence for your workflow is that Rector alone does not produce a committable diff on a real project. As the documentation puts it, your project needs to have a coding standard tool and a set of formatting rules so it can make Rector's output nice and shiny again. The maintainers use ECS, the easy-coding-standard, and point at their own configuration for it. So the practical pipeline is two stages: Rector decides what the code should say, and a coding standard decides how it looks. If you skip the second stage you will spend your review time on whitespace instead of semantics, and if you wire the second stage into your commit hooks instead of running it manually, the output of the migration becomes reviewable as a meaningful diff.

Files that mix PHP and HTML must be verified by hand after applying

The second drawback is narrower but sharper, and it is stated as a warning rather than a caveat. When you apply changes to files with PHP and HTML content, you may need to manually verify the changed file after applying the changes. Templates are the case this describes. A view file is not a clean PHP program; it is a document with islands of PHP inside it, and the parser has to reconstruct those islands from markup that carries its own structure and its own formatting expectations. Where a tool reasons about an abstract syntax tree, a template is the least tree-like input in a PHP project, and the documentation is candid that the output may be unexpected there. The operational consequence is that a blanket run over a codebase containing templates is the wrong default, because the files most exposed to damage are the ones your end users read on every page load. Two mitigations are available without leaving the documented workflow. You can scope the run to the directory that holds your PHP application code and leave view files out of the path, since the path is just an argument to the command. And you can treat template files as a separate review pass with a human reading each diff, rather than trusting the automated output the way you trust a diff on a service class.

Parallel mode breaks on Windows more often, and the shell is the suspect

Parallel execution is the third documented drawback, and its failure mode is environmental rather than logical. Rector in parallel mode will work most of the time for most operating systems. On Windows, you may encounter issues that remain unresolvable even after following the Troubleshooting Parallel guide. The remedy given is not a configuration change but a shell change: check whether you are using Powershell 7, abbreviated pwsh, and if so change your terminal to command prompt, cmd, or bash for Windows. That is a small paragraph with an outsized effect on CI design. It means a pipeline that forks processes can behave differently depending on which terminal invokes it, and that a green run on a developer laptop running bash is not evidence the same command works on a Windows agent running pwsh. If your team is cross-platform, decide the shell explicitly in the CI configuration rather than inheriting whatever the runner defaults to. The parallel mode itself is worth wanting on a large codebase, since it is the difference between a migration that finishes while you make lunch and one that does not, so the documented remedy on Windows is to switch the terminal away from PowerShell 7 to cmd or bash.

When Rector fails, --debug or --xdebug gives you the nested exception

Debugging a static refactoring tool is awkward because the failure is a transformation rather than a line of your code, and the project offers two escape hatches. The first is the --debug option, which prints nested exceptions output:

bash
vendor/bin/rector src/Controller --dry-run --debug

The second is Xdebug. You make sure Xdebug is installed and configured, then add the --xdebug option when running Rector:

bash
vendor/bin/rector src/Controller --dry-run --xdebug

Both examples keep --dry-run, which is the point to carry forward: you are debugging what Rector intends to do, not what it already wrote. For the narrower case of understanding a single node, Rector ships two helpers that pretty-print AST nodes, and the example given creates a string node and prints it as PHP code displays it:

php
use PhpParser\Node\Scalar\String_;
$node = new String_('hello world!');

// prints node to string, as PHP code displays it
print_node($node);

For anyone writing or reading rules, that helper is more valuable than it looks, because it lets you confirm what the parser produced instead of guessing from the output file. If you want the full internals rather than the README, there is a book, Rector - The Power of Automated Refactoring, that walks through the setup and how to create and test your own rules.

Editorial conclusion

Adopt Rector when you have a large legacy codebase pinned to an old PHP or framework version and a test suite that can prove the rewrite did not break behaviour, because that safety net is what makes an automated migration acceptable. Do not point it at template files or any PHP and HTML mixture without reading the diff afterwards, and pair it with a coding standard tool from day one. Before enabling parallel mode on Windows, check whether your shell is PowerShell 7.

Frequently asked questions

How do I install Rector?

Install it as a development dependency with composer require rector/rector --dev. You then create a rector.php in your project root that calls RectorConfig::configure(), registering rules with withRules or prepared bundles with withPreparedSets, and run it through vendor/bin/rector.

How do I use Rector with PHP?

Run vendor/bin/rector src --dry-run first to see a diff of the files it would change, then run vendor/bin/rector src without the flag to apply them. Rector supports upgrades from PHP 5.3 to 8.5, and framework support such as Symfony, PHPUnit and Doctrine lives in separate extension repositories.

Does Rector produce correctly formatted PHP code?

Not on its own. Rector is built on nikic/php-parser and an AST does not know about spaces, so writing output back to a file produces poorly formatted code in both PHP and docblock annotations. The project states that your project needs a coding standard tool with formatting rules, and the maintainers use ECS with their own configuration.

Is it safe to run Rector over template files that mix PHP and HTML?

The documentation warns that applying changes to files with PHP and HTML content may require you to manually verify the changed file afterwards. A practical response is to scope the run to your application code and review template diffs individually rather than trusting the automated output.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. rectorphp/rector on GitHub
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/rectorphp-rector.svg)](https://hysenlabs.com/projects/rectorphp-rector)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/rectorphp-rector.svg)](https://hysenlabs.com/projects/rectorphp-rector)

Was this useful?