Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rector Rules Laravel Package

guanguans/rector-rules

A collection of custom Rector rules for PHP and Laravel projects that automates code refactoring, modernization, and upgrades. Register the rule sets in your rector.php config to enforce consistent standards and streamline migrations with less manual work.

View on GitHub
Deep Wiki
Context7

Getting Started

guanguans/rector-rules is a dev-only Rector extension — it does not ship runtime code. Treat it like PHPStan/Rector itself: install in require-dev, wire it into rector.php, and run it over your codebase.

Minimal setup

composer require --dev guanguans/rector-rules rector/rector

Then publish/point at a config (the package exposes rule sets you can ->withPaths() on) and create or extend rector.php:

use Rector\Config\RectorConfig;
use Guanguans\RectorRules\Set\...;   // set class from `vendor/guanguans/rector-rules/src/Set`

return RectorConfig::configure()
    ->withPaths([__DIR__ . '/app', __DIR__ . '/src', __DIR__ . '/tests'])
    ->withSets([
        // package set(s) you want
    ]);

Where to look first

  1. vendor/guanguans/rector-rules/src/ — the rule classes are the documentation. Each rule's getNodeTypes() + refactor() tells you exactly what it rewrites.
  2. Any Set/ directory — prefer registering a set over hand-listing individual rules; sets are the package's supported surface.
  3. vendor/guanguans/rector-rules/README.md and the repo's own rector.php — the package dogfoods its rules, so its config is a working example.

First use case

A safe, high-value entry point: run Rector in dry-run before you trust it.

vendor/bin/rector process --dry-run

Start with one rule on one directory (e.g. a single rule against app/), review the diff, commit, then widen. The 1.9.2 addition — RenameStaticMethodRector, aimed at Str UUID handling — is a good example of the kind of rule you introduce deliberately: it renames static calls such as Str::uuid()/Str::orderedUuid() to their newer equivalents (e.g. Str::uuid7()), so you want it scoped and reviewed rather than dropped into a global set on a 200k-line codebase.

Implementation Patterns

Pattern 1 — Dry-run → diff → commit loop (default workflow)

Never run this in the same process as a composer update. Do it as its own committed change:

vendor/bin/rector process --dry-run --clear-cache
vendor/bin/rector process
git diff   # review before committing

--clear-cache matters when you change the config between runs; Rector caches aggressively and will silently keep old results.

Pattern 2 — Composer scripts per rule-set

Give each migration an explicit, named handle so future-you knows why code looks the way it does:

"scripts": {
    "refactor": "rector process",
    "refactor:dry": "rector process --dry-run",
    "refactor:str-uuid": "rector process app/ --only='Guanguans\\RectorRules\\Rector\\RenameStaticMethodRector'"
}

--only / --rules per invocation is the cheapest way to isolate a single rule (new or otherwise) without editing rector.php and re-caching.

Pattern 3 — Layer rules by target path

Keep framework-facing code and your own code under different rule sets. rector.php supports multiple withPaths()/withSets() calls, so:

  • app/ → conservative set (renames, dead-code-adjacent rules only)
  • database/, config/ → exclude UUID-related rewrites entirely; schema/config strings are often intentionally literal
  • tests/ → run everything, then fix fixtures by hand

Pattern 4 — CI gate, not CI auto-fix

Add rector process --dry-run as a required job after the initial migration is merged. This catches regressions where a developer reintroduces an old Str::uuid() call. Do not let CI auto-commit Rector output — reviewed refactors only.

Pattern 5 — Pair renames with the Laravel version bump

RenameStaticMethodRector for Str UUIDs is only correct if your laravel/framework constraint actually provides the target method. Sequence it as: bump laravel/framework → run the rename rule → run the test suite. Reversing the order produces calls to methods that don't exist yet and a fatal error that looks like a Rector bug.

Pattern 6 — Wrap third-party/vendored code out of scope

Always exclude vendor/, storage/, bootstrap/cache/, and any generated stubs (_ide_helper.php, *.ide_helper.models.php). Rector will happily "fix" generated files that get overwritten on the next composer install.

Gotchas and Tips

Static-method rules only see static calls. RenameStaticMethodRector matches Str::uuid() AST nodes. It will not touch:

  • 'Illuminate\Support\Str::uuid' — string callables
  • [Str::class, 'uuid'] — array callables
  • call_user_func([Str::class, 'uuid'])
  • $class::uuid() where $class is a variable
  • Facade-style calls like Str::uuid() aliased behind your own wrapper class

Grep for the method name as a string before declaring the migration done.

Also check you're not fighting an existing alias. If your codebase imports Str as something other than Illuminate\Support\Str, or uses use Illuminate\Support\Str; with a different FQCN, verify the rule's matching is FQCN-based. If a change isn't applied, inspect the use statements first — not the rule.

Rector cache invalidation is the #1 "the rule does nothing" cause. Rule added but no diff? In order: --clear-cache, confirm the rule is actually in your withSets()/withRules() (a set may not include the newest rule), confirm the file is under withPaths(), confirm it isn't matched by withSkip().

Order of rules matters. Renames that change the class being called (A::foo() → B::foo()) followed by a rule that then operates on B will run in registration order. If a second rule "misses" a call the first rule just created, run Rector twice (it converges) or reorder registrations.

--dry-run exit codes are CI-hostile by default. Check your Rector version's flag for failing on diffs; otherwise your "gate" passes green while printing diffs. Verify the job actually goes red on a deliberate violation.

Pin the version. This is a code-mutating dev dependency on a fast-moving 1.x. Use a caret constraint but commit composer.lock, and treat minor bumps as review-worthy — a rule's rewrite semantics changing between 1.9.1 and 1.9.3 can silently alter a large diff.

Extension points. Custom rules are a single class implementing Rector\Contract\Rector\RectorInterface (typically extending AbstractRector). If the package's Str rule doesn't cover your wrapper, write a thin rule that delegates — call the package rule from your own test suite to keep behaviour aligned. Register personal rules under a local namespace, not in vendor/-adjacent set files, so composer update doesn't clobber them.

Verify with tests, not with the diff. A rename that compiles can still break behaviour if the old method had subtly different output (UUID v4 vs v7 ordering is a real behavioural difference — v7 is time-sortable). Anywhere you assert on ID format, sort order, or DB index locality, re-read the assertion after the rename.

Debugging a rule that misfires: use --debug and Rector's --output-format=json to see file/line attribution, then reduce to a minimal fixture file and run --only on it. If it reproduces, you have a bug report; if not, it's a config/path problem.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect