emmanuelballery/eb-plantumlbundle
A Symfony bundle that generates PlantUML diagrams from your Doctrine entities, making it easy to visualize and document your data model. Export class diagrams automatically to keep documentation in sync with your codebase.
First, a stack check that determines everything. emmanuelballery/eb-plantumlbundle is a Symfony bundle built on Doctrine ORM metadata, not a Laravel package. It has no service providers, no facade, no package:discover support, and it reads Doctrine\ORM\Mapping\ClassMetadata — not Eloquent models. If your target application is Laravel/Eloquent, this package will not generate anything useful for you, and no amount of wiring will fix that. The honest day-to-day answer for a pure Laravel shop is: don't install it; use it as a reference implementation (see Implementation Patterns).
You have real day-to-day leverage in exactly three situations:
For cases 1–2, minimal steps:
composer require --dev emmanuelballery/eb-plantuml-bundle
Register the bundle in config/bundles.php (dev/test only). Then look in this order:
bin/console list | grep eb — this is your real command surface. --help on each is more reliable than the README.vendor/emmanuelballery/eb-plantuml-bundle/DependencyInjection/Configuration.php — the authoritative list of config keys and defaults. Read this before you write any YAML; it's frequently ahead of the docs.vendor/emmanuelballery/eb-plantuml-bundle/Command/ — shows where entity scanning and PlantUML rendering actually live, useful if you're going to fork or reimplement.Minimal config (config/packages/dev/eb_plant_uml.yaml):
eb_plant_uml:
output: '%kernel.project_dir%/var/plantuml'
First use case: point it at a representative bundle's entities and dump a .puml class diagram.
bin/console eb:plantuml:... --help # confirm exact command name in your version
Decide your renderer up front:
plantuml.jar: emit .puml, render yourself with java -jar plantuml.jar -tsvg. Offline and deterministic, more setup.Treat diagrams as build artifacts, not committed files. Generate into var/plantuml/ (gitignored) and regenerate on demand. Committed .puml rots within a sprint; committed .svg produces noisy, unreviewable diffs. If you need diagrams in docs, publish the rendered SVG from CI, not from a laptop.
Wrap the command in a Composer script or Makefile, so nobody has to remember the invocation or the cache clear:
"scripts": {
"diagrams": [
"@php bin/console cache:clear --env=dev",
"@php bin/console eb:plantuml:..."
]
}
The cache clear matters: Doctrine metadata and the bundle's scan results are cached, and a stale cache is the #1 cause of "my new entity isn't in the diagram."
The Laravel-native equivalent (the actual day-to-day pattern for Laravel devs). The interesting thing about this bundle isn't its code — it's the workflow. You can reproduce it in a few hours with an Artisan command that walks Eloquent models:
// app/Console/Commands/GenerateErd.php
foreach (glob(app_path('Models/*.php')) as $file) {
$model = new (getModelClass($file))();
$table = $model->getTable();
$columns = Schema::getColumnListing($table);
$relations = collect((new ReflectionClass($model))->getMethods())
->filter(fn($m) => $m->getReturnType() instanceof \ReflectionNamedType
&& str_contains($m->getReturnType()->getName(), 'Relations'))
->map(fn($m) => $m->getReturnType()->getName());
// emit PlantUML: class $table { ... } + $table --> $related
}
Same discipline: write .puml text, render with plantuml.jar -tsvg, publish in CI. Mirror the bundle's output format so reviewers see familiar diagrams, and so you can swap to the bundle later if you migrate to Doctrine.
Scope by domain, not whole application. On a 40-entity codebase a single diagram is fine; at 150+ it's an unreadable hairball. Emit one diagram per bounded context / bundle / namespace, and let people open the relevant one.
CI integration. A nightly (or PR-gated) job that generates SVG and uploads as an artifact gives you the "docs as build output" property without any human remembering to do it. Diffing the SVGs or the .puml between branches is a lightweight model-churn signal — useful for planning ("why did this area change this sprint?").
#[ORM\...] attributes (Symfony 5.4+ era), check the bundle even parses them; if it predates PHP 8 attributes, expect friction.bin/console cache:clear and, in dev, doctrine:cache:clear-metadata. This is the most common "bug" report..puml text and rendering with a local plantuml.jar in a container step; it removes a network dependency and gives deterministic output.symfony/*, PHP, and doctrine/orm versions before any commitment. If it doesn't install cleanly, walk away — the functionality is replicable in a day.Configuration.php over the README. The config tree in DependencyInjection/ is the source of truth for keys, defaults, and allowed values — docs lag.Command/ and the DI namespace, so you can swap the PlantUML emitter (text vs. URL-encoded SVG) without touching the entity walker. That's the seam to build on if you decide to internalize the tool.How can I help you explore Laravel packages today?