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 Doctrine Laravel Package

rector/rector-doctrine

Rector Doctrine provides Rector rules to automate refactoring and upgrading Doctrine ORM/DBAL code in PHP projects. It helps modernize annotations, mappings, queries, and legacy APIs with safe, repeatable code transformations.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package as a dev dependency alongside Rector, then register a Doctrine set in rector.php:

composer require --dev rector/rector rector/rector-doctrine
<?php
// rector.php
use Rector\Config\RectorConfig;
use Rector\Doctrine\Set\DoctrineSetList;

return RectorConfig::configure()
    ->withPaths([__DIR__ . '/src/Entity'])
    ->withSets([
        DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES,
    ]);

If you are on an older Rector that still uses the closure form:

use Rector\Config\RectorConfig;
use Rector\Doctrine\Set\DoctrineSetList;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->paths([__DIR__ . '/src/Entity']);
    $rectorConfig->sets([DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES]);
};

Where to look first: open Rector\Doctrine\Set\DoctrineSetList in vendor/rector/rector-doctrine/src/Set/. The class constants are the public API—every set you can safely reference lives there (DOCTRINE_25, DOCTRINE_26, DOCTRINE_27, DOCTRINE_CODE_QUALITY, ANNOTATIONS_TO_ATTRIBUTES, GEDMO_ANNOTATIONS_TO_ATTRIBUTES, TYPED_COLLECTIONS). Skim config/sets/ to see which rules each set composes; that is your fastest way to know what a set will actually change.

First use case: migrate annotation mapping to PHP 8 attributes on an existing entity folder. Run dry first:

vendor/bin/rector process src/Entity --dry-run

Review the proposed diffs, then rerun without --dry-run on a dedicated branch. This is the highest-value, lowest-risk win the package offers and the reason most teams install it.

Implementation Patterns

1. Annotation → attribute migration, in isolation. Run this set alone, in its own commit. Mixing it with code-quality or dead-code sets makes the diff unreviewable. Restrict withPaths() to entity directories only; the annotation rules are not useful on services, DTOs, or migrations.

->withSets([DoctrineSetList::ANNOTATIONS_TO_ATTRIBUTES])
->withSkip([
    \Rector\Doctrine\CodeQuality\Rector\Class_\SomeRuleYouDontWantRector::class,
])

2. Staged version upgrades. Treat DOCTRINE_25, DOCTRINE_26, and DOCTRINE_27 as an ordered ladder, not a single set. Run one, commit, run tests, then the next. This surfaces a Doctrine upgrade regression against a known small diff instead of a giant one.

->withSets([
    DoctrineSetList::DOCTRINE_25,
    DoctrineSetList::DOCTRINE_26,
    DoctrineSetList::DOCTRINE_27,
])

Order matters: if you are also converting annotations to attributes, run ANNOTATIONS_TO_ATTRIBUTES first, commit, then run the version sets. Attribute mapping is the prerequisite for several Doctrine 3-era expectations, and it keeps each step independently revertible.

3. Code-quality set for entity hygiene. DOCTRINE_CODE_QUALITY normalizes common entity mistakes—mismatched default values on properties ($id = false on an integer id), weak collection docblocks, and other patterns that cause subtle hydration or typing bugs. Run it on entities as a periodic cleanup rather than on every CI build.

4. Typed collections rollout. TYPED_COLLECTIONS adds generic-native docblocks and typed Collection properties (@var Collection<int, Item> / Collection). Use it to enable PHPStan/Rector type analysis on aggregates. Expect to initialize properties (= new ArrayCollection()) manually afterward; the rule narrows types but should not be trusted to restructure constructors.

5. Gedmo and extension mappings. If you use gedmo/doctrine-extensions, GEDMO_ANNOTATIONS_TO_ATTRIBUTES converts @Gedmo\Timestampable, @Gedmo\Slug, etc. Run it after the ORM annotation conversion, and remember custom bundles (JMS serializer, API Platform) have their own mappings—this package does not convert those.

6. CI guardrail. A rector process --dry-run job scoped to entities catches regressions where a developer reintroduces an old Doctrine pattern (or a merge conflict reverts an attribute). Keep the process step and the dry-run step on the same config file to avoid drift.

7. Monorepo scoping. In a multi-module repo, create one rector.php per module with only the Doctrine paths for that module, or use withPaths() with explicit entity globs. Do not point the Doctrine sets at the whole src/—reflection and annotation parsing across thousands of unrelated files is slow and produces noise.

Gotchas and Tips

  • Attributes require support on both sides. Converting to PHP attributes implies PHP 8.0+ and Doctrine ORM 2.9+ (2.11+ realistically, for full attribute mapping). Check composer.json before running ANNOTATIONS_TO_ATTRIBUTES; a half-converted codebase on an older ORM will fail at runtime, not at Rector time.
  • Keep doctrine/annotations installed during the migration. The annotation rules parse existing annotations; removing the annotations package before you have finished converting leaves you unable to run the conversion again on remaining files.
  • Cache lies after config changes. If a rule seems to do nothing, run vendor/bin/rector process ... --clear-cache. Rector's cache keys on config, but editing a set list mid-run is a common source of "why isn't it applying?"
  • Dry-run is mandatory. This package has a small maintainer surface (≈80 stars) and limited rule coverage. Always review the diff; never run on a dirty tree.
  • Import style matters for attributes. The conversion expects use Doctrine\ORM\Mapping as ORM; and emits #[ORM\Column(...)]. If your project uses use Doctrine\ORM\Mapping\Column;, either adjust with withImportNames() settings or do a follow-up cleanup. Mixed import styles make the diff noisy.
  • Rule order within a set is not your order. Sets are curated internally. If you write a custom withRules([...]) list mixing Doctrine rules with your own, verify precedence—annotation-to-attribute rules should precede any rule that inspects mapping metadata.
  • Skip via FQCN. withSkip() for these rules requires the full rule class name (e.g. Rector\Doctrine\...\Rector), not the set name. Grab it from the dry-run output.
  • Typed collections change inference, not runtime. Adding @var Collection<int, Foo> can unlock strict PHPStan rules that then flag existing untyped usages. Roll it out module-by-module and pair it with a static-analysis run, not just a test run.
  • Not a Doctrine 3 migration tool. Version sets cover the 2.5→2.7 deprecation span. For Doctrine 3 removals (e.g. dropped APIs, ObjectManager interface changes), expect to write custom Rector rules—this package's coverage is intentionally narrow.
  • Extension points: write a small custom AbstractRector subclass for any mapping pattern the package misses (custom annotations, project-specific base entities), and register it in withRules(). Keep it in tools/rector/ so it is versioned with the project rather than the vendor tree.
  • Commit granularity: one set per commit, tests green between commits. This is the only reliable way to bisect a bad conversion when an entity suddenly stops hydrating.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings