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

Laravel Model Annotator Laravel Package

dottedai/laravel-model-annotator

Automatically generates PHPDoc annotations for Laravel Eloquent models, adding @property, @method and relationship hints so your IDE and static analysers understand attributes, scopes and relations without guesswork.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a lightweight codegen utility: an artisan command that inspects your database schema and Eloquent relationship definitions, then writes PHPDoc blocks onto your model classes (property annotations for columns, relationship return types, and @property casts). It is the kind of thing you install once per project and then fold into your working loop.

Minimal steps:

  1. Install it as a dev dependency (you almost never want this in production — it rewrites source files):
    composer require --dev dottedai/laravel-model-annotator
    
  2. If the package ships a config file, publish it and skim the defaults before the first run. Check vendor/dottedai/laravel-model-annotator/ for the service provider's publishes() calls and the command's $signature — with a package this small, reading the command class takes two minutes and is faster than guessing at flags.
  3. Run the command against a single model first, not the whole app:
    php artisan model:annotate App\\Models\\User
    
    (Confirm the exact command name/arguments from php artisan list | grep annotate.)
  4. Open the annotated model and diff it. You want to see @property lines for every column, correct @property-read for belongsTo/hasMany, and @property Carbon $created_at-style cast awareness.

First use case: a model that your IDE and static analyser currently treat as a black hole. Pick the model you touch most in a given week, run the annotation, and confirm $user->email_address now resolves in your editor without "undefined property" noise. That one model is your proof of value; anything beyond that is rollout.

Where to look first: the command class itself (source of truth for flags like --all, --force, --no-relations), any config file, and the package's own tests — a zero-star package's tests tell you more about intended behaviour than its README.

Implementation Patterns

Single-model, on-demand runs. The safest daily pattern. Annotate the model you're actively working on after a migration adds or renames columns:

php artisan model:annotate App\\Models\\Order --force

Keep this as a muscle-memory step after php artisan migrate on a branch that changes schema.

Batch baseline, then incremental. Do one full pass to bring the whole App\Models namespace up to date, commit the resulting PHPDoc diff as a pure "no logic changed" commit, then rely on single-model runs from there. A single giant annotation commit is reviewable; interleaved annotation noise inside feature PRs is not.

CI drift check. If the command is idempotent (annotations deterministic for a given schema + model), add a CI job that runs it and fails on a dirty working tree:

php artisan model:annotate --all
git diff --exit-code app/Models

This keeps annotations from going stale silently. Verify idempotency locally first — run twice and confirm the second run produces an empty diff. If it isn't deterministic, drop this pattern.

Pair with static analysis. The real payoff is feeding cleaner types to PHPStan/Larastan or Psalm. Generated @property blocks reduce the need for manual @property maintenance and catch relationship nullability mistakes at analysis time. Order matters: run the annotator before static analysis in your pipeline.

Use annotations as discovery documentation. On an unfamiliar codebase, running the annotator over all models gives you a fast, accurate map of schema columns, casts, and relationship directions directly in the model files — often more reliable than reading migrations, because it reflects the live schema.

Respect hand-written docblocks. If the tool appends rather than replaces, adopt a convention: keep your prose docblock at the top and let the tool own the @property/@method block below a separator, so regeneration doesn't nuke your notes. If the tool fully replaces the block, keep explanatory prose in comments above the class declaration, not in the PHPDoc.

Gotchas and Tips

  • Schema must be migrated first. The command reads the actual database (or a schema snapshot), not your migration files. Annotating before migrate on a fresh clone produces empty or wrong annotations. Run migrations, then annotate.
  • Source-file rewriting is destructive by default. Expect --force/overwrite semantics or prompts. Commit before the first run so you can git diff and git checkout cleanly if a whole namespace gets mangled.
  • @property vs @property-read. Getters for relationships and accessors should be -read; if the tool guesses wrong you'll get spurious "read-only property modified" static-analysis errors. Spot-check one belongsTo and one accessor-backed attribute.
  • Dynamic/accessor attributes can be missing. Columns added via $appends accessors don't exist in the schema, so they may not appear. Add those manually and expect to re-add them if the tool fully replaces the docblock.
  • Interface-typed or polymorphic relationships (morphTo) often degrade to generic annotations. Review those by hand.
  • Overlap with barryvdh/laravel-ide-helper. If you already run ide-helper:models, don't run both — they fight over the same docblocks. Pick one owner for @property annotations. This package is narrower (schema + relations + casts) but the conflict is real; audit existing model docblocks before adopting.
  • Connection/schema scoping. Multi-database or multi-schema apps may only inspect the default connection. Check whether a --connection flag exists; if not, that's a hard limitation for sharded or tenant-per-database setups.
  • Don't commit generated noise blindly into feature PRs. Annotations should land in dedicated commits so schema changes stay reviewable and a bad generator run is a one-commit revert.
  • Zero-star, zero-dependent package = treat as vendored code. Read the command source, pin the version in composer.json, and be prepared to fork it. It's small enough that a fork is cheaper than waiting on maintainer response if the tool breaks on a new Laravel/PHP version. There's no ecosystem safety net here.
  • Extension point to look for: any config-driven template or stub the command renders from. If it exists, that's your place to enforce your team's docblock style centrally instead of post-editing.
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.
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
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route