Limitations

Rector reads code, it never runs it. Knowing where that line is saves most of the "why didn't Rector change this" questions.

Rector sees what PHPStan sees

Rector resolves types with PHPStan. What PHPStan knows, Rector knows, and vice versa. If a method call is on a mixed value, Rector cannot rename it, add a return type to it or remove it as dead code. That's why New Project asks for PHPStan without a baseline first: a baseline hides thousands of unknown types from both tools.

No runtime, no magic

Rector loads classes with static reflection. It does not boot your framework, run your container or execute your bootstrap. Anything only known at runtime is invisible:

  • magic __get, __call and __callStatic without docblocks
  • services resolved by string name from a container
  • classes generated on the fly

Some framework rules can read a dumped container, see the Symfony integration.

Rector does not format code

Rector prints code with php-parser and keeps the original formatting where it can, but it may leave an extra space or an unaligned line. Run a coding standard tool right after Rector, in the same CI job. Easy Coding Standard is the recommended one.

Templates are not PHP

Rector processes .php files only, unless you add extensions with withFileExtensions(). It does not understand Twig, Blade or Latte, so a renamed method is not renamed inside templates. Search templates by hand or with a framework-specific tool after such a change.

Rules are conservative on purpose

Many rules only touch private and final code, because a change to a public method of a non-final class can break children and callers Rector cannot see. If your project is under your control, turn that on with withTreatClassesAsFinal(), see Config Configuration.