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

Doctrine Diagram Bundle Laravel Package

jawira/doctrine-diagram-bundle

A Symfony bundle for generating diagrams from Doctrine entities. Visualize your ORM mappings as ER diagrams to inspect relationships, schema structure, and entity connections, making documentation and debugging easier.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check. This is a Symfony bundle, not a Laravel package. It has no service provider, no auto-discovery, and its DependencyInjection/Extension registration is meaningless inside a Laravel app. It is also Doctrine ORM–specific — it reads entity metadata, not your Eloquent models. For a typical Laravel/Eloquent codebase it will produce nothing useful, and pulling symfony/framework-bundle into a Laravel app just to get a console command is a bad trade. v2.0.0 does not change this; if anything, dropping Symfony 6 support makes the bundle even less appealing to wire into anything other than a current Symfony app.

Two workable paths:

  1. Laravel + Eloquent (the common case): skip the bundle. Use beyondcode/laravel-er-diagram-generator, which introspects your actual schema and is the Laravel-native equivalent. Come back here only if you specifically want this tool's output style.
  2. Laravel + Doctrine ORM (via atrauzzi/laravel-doctrine or a hand-rolled EntityManager), or a standalone script against a Doctrine project. Install the library, not the bundle. v2.0.0 requires PHP 8.2+ — confirm your app/CI matrix before adopting:
# Graphviz is the actual rendering engine — install it first
brew install graphviz          # macOS
apt-get install -y graphviz    # Debian/Ubuntu (add to your Dockerfile + CI image)
dot -V                         # must succeed before anything else

composer require --dev jawira/doctrine-diagram:^2.0

Where to look first:

  • vendor/jawira/doctrine-diagram/README.md — the library API and CLI flags. The docs were rewritten for v2 in PR #85, so this release is the first time the README actually matches the flags. Still run vendor/bin/doctrine-diagram --help and trust that output, since flags have moved between releases.
  • If you did install the bundle to read it: src/DependencyInjection/Configuration.php is the single source of truth for every option (output path, format, theme, entity-manager selection). Read it instead of guessing at YAML keys.
  • src/Command/ in the bundle — shows exactly how the library is wired to an EntityManager, which is the 20 lines you need to replicate in Laravel.

First use case: generate a diagram into docs/ for onboarding and PR review, from an Artisan command:

// app/Console/Commands/ErDiagram.php
protected $signature = 'db:er-diagram {--format=svg} {--out=docs/er} {--include=*} {--exclude=*}';

public function handle(): int
{
    if (!class_exists(\Doctrine\ORM\EntityManager::class)) {
        $this->error('doctrine/orm required — this package reads entity metadata.');
        return self::FAILURE;
    }

    $config = \Doctrine\ORM\ORMSetup::createAttributeMetadataConfiguration(
        paths: [app_path('Entities')],
        isDevMode: true,
    );

    $connection = \Doctrine\DBAL\DriverManager::getConnection([
        'driver' => 'pdo_pgsql',
        'host'   => config('database.connections.pgsql.host'),
        'dbname' => config('database.connections.pgsql.database'),
        'user'   => config('database.connections.pgsql.username'),
        'password' => config('database.connections.pgsql.password'),
    ], $config);

    $em = new \Doctrine\ORM\EntityManager($connection, $config);

    // Hand $em to the package's generator (see library README for the exact
    // class/signature in your pinned version), target: storage_path('../docs/er.svg').
    // If invoking the CLI: --include and --exclude are now repeatable flags (v2),
    // NOT comma-separated lists.

    return self::SUCCESS;
}

Implementation Patterns

Generate .dot first, render second. Ask for --format=dot, commit or inspect that intermediate file, then render to SVG/PNG. It cleanly separates "the package found the wrong entities" from "Graphviz choked on the layout," which are otherwise indistinguishable failures.

Use --include to carve boundaries (new in v2). v2.0.0 adds an include filter alongside the existing exclude. This is the cleanest way to scope a diagram to a bounded context: --include='App\Entities\Billing\*' emits one file per module without hand-maintaining entity paths. Compose with --exclude to prune join tables from within an included set.

Breaking CLI change: --exclude is now repeatable, not comma-separated. v1 allowed --exclude=a,b,c; v2 expects --exclude=a --exclude=b --exclude=c. A migrated command that still passes a CSV string will not exclude what you think — it'll treat the whole string as one pattern. Audit every wrapper, Makefile target, and CI step for old-form comma lists. Same applies to --include.

Artifact-in-CI pattern. Run the generator on a schedule or on PRs touching entities, upload SVG/PNG as a build artifact, and only commit to docs/ on main. Avoid committing on every PR — binary/image diffs are noise and cause merge conflicts.

# .github/workflows/diagram.yml
- run: sudo apt-get install -y graphviz
- run: php artisan db:er-diagram --format=svg --out=docs/er --include='App\Entities\Billing\*'
- uses: actions/upload-artifact@v4
  with: { name: er-diagram, path: docs/er.svg }

Split by bounded context, not one mega-diagram. A single diagram of 80+ tables is unreadable no matter how good the layout. With v2's --include, this is now cheap: emit one diagram per module, per entity-manager, and let the docs site hold the index. The render step is cheap; the reading is not.

Docker/CI parity. The Graphviz binary is the dependency that bites you, not the composer package. Add graphviz to your app image (RUN apt-get install -y graphviz) even though the package is dev-only, or every CI run of the command fails with an opaque non-zero process exit.

Wrap it, don't sprinkle it. One ErDiagram command (or a scripts/ PHP file) that owns config, paths, and error handling. Then composer diagram, a Makefile target, or a scheduler entry can all call the same thing. Don't let the raw vendor binary get invoked from three different places — especially now that flag syntax changed between majors.

Post-process the DOT. Because --format=dot gives you plain Graphviz source, you can pipe it through dot -Tsvg | ..., convert to Mermaid for a wiki, or apply your own rankdir/splines overrides. That's the real extension point when the built-in themes don't match your docs style.

Pair with migration review. Generate the diagram as part of reviewing a schema-changing PR: before/after diagrams side by side is often faster to reason about than reading a 200-line migration.

Gotchas and Tips

It cannot see Eloquent models. This is the #1 misunderstanding. doctrine/dbal alone (which Laravel pulls in for ->change() in migrations) provides zero entity metadata. The generator will either error or emit an empty graph. You need doctrine/orm plus actual mapped entities. If your models extend Illuminate\Database\Eloquent\Model, this package has nothing to draw.

v2.0.0 is a breaking release. Three things bite on upgrade: (1) PHP 8.2 minimum — anything on 8.1 must stay on v1; (2) --exclude is no longer comma-separated — update every wrapper and CI invocation; (3) Symfony 6 dropped — irrelevant if you only use the library, but if you did wire the bundle, the upgrade is blocked on Symfony 7. Read the upgrade path before bumping the constraint.

Bundle ≠ package. Don't follow the Symfony README's config/bundles.php step; it doesn't exist in Laravel. Install the library directly to avoid dragging symfony/framework-bundle into your dependency graph.

Attribute vs annotation mapping. Modern Doctrine uses PHP 8 attributes; most tutorials and older examples still show @ORM\Entity docblocks. Mixing them yields "no entities found" with no useful message. Ensure createAttributeMetadataConfiguration matches the mapping style actually present in your entity classes.

Graphviz format support varies. svg and png are essentially always available; pdf requires cairo support compiled in. If a format silently fails, test it directly: echo 'digraph{a->b}' | dot -Tpdf > /dev/null.

Output paths. Relative paths resolve against the process working directory, and the parent directory usually must already exist. Use absolute paths (storage_path(), base_path('docs')) and mkdir defensively.

Keep it dev-only. --dev in composer and --no-dev in production installs. There is no reason for a diagram generator to be in a production image.

Large schemas break layout, not the tool. Graphviz's layout engines degrade badly past a few dozen nodes. Symptoms: hairball edges, overlapping labels, 10-minute renders. Fix with clustering, rankdir=LR, pruning join tables, or splitting into per-module diagrams via --include — not by tweaking the package.

Verify the release actually exists. Metadata here lists a release dated 2026-06-27, which is worth confirming against Packagist before pinning to it. Prefer "jawira/doctrine-diagram": "^2.0" now that v2 is a stable major with a refreshed doc set, but keep the minor pinned for this low-traffic package.

Maintenance risk is real. ~80 stars and near-zero dependents means a small bus factor — the fact that v2 shipped at all is reassuring, but one maintainer is still one maintainer. Keep the wrapper thin so swapping to beyondcode/laravel-er-diagram-generator, schemaspy, or a raw doctrine/orm + Graphviz script is an afternoon, not a rewrite. The .dot intermediate file is your insurance policy — it's a portable format.

Debugging checklist when the diagram is empty or wrong: (1) dot -V works, (2) entities are discovered — dump $em->getMetadataFactory()->getAllMetadata(), (3) the metadata is fully mapped (run doctrine:schema:validate equivalent), (4) filters aren't over-excluding — try with no --include/--exclude first, (5) you asked for .dot and confirmed nodes exist before rendering.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib