Browse documentationOpen

byrcsc/laravel-cartographer · 1.x

Introduction.

What Laravel Cartographer generates, where the diagram comes from, what it deliberately leaves out, and how to decide whether it fits your application.

Laravel Cartographer turns an existing Laravel application into a Mermaid entity relationship diagram. One Artisan command reads your Eloquent models and your database schema, then writes a Markdown file that renders directly on GitHub and GitLab.

php artisan cartographer:erd

The diagram lives in the repository, so a schema change shows up in the pull request diff next to the migration that caused it.

RequirementSupported versions
PHP8.2, 8.3, 8.4
Laravel11.x, 12.x
DatabasesMySQL, PostgreSQL, SQLite

The package follows semantic versioning: upgrading within 1.x is safe. Source and issues live at github.com/byrcsc/laravel-cartographer.

The two sources

Cartographer never reads a row of your data. A diagram is assembled from two inputs, and every fact in it comes from one of them.

Your models supply the relationships. Cartographer instantiates each discovered model and invokes its relation methods, so foreign keys, pivot tables, and polymorphic names come out exactly as Eloquent resolves them. A belongsTo with a custom foreign key is read from the relation object, not guessed from a naming convention.

Your database supplies the structure. Tables, columns, types, primary keys, unique indexes, and foreign key constraints come from Laravel's native schema builder on a live connection. Because the structure is read from the database rather than parsed out of migration files, it stays correct on applications with squashed migrations, raw SQL migrations, and years of migration history.

What a diagram looks like

Relationships first, entities second:

erDiagram
    posts }o--|| categories : "category"
    posts ||--o{ comments : "commentable (morph)"
    posts }o--o{ tags : "tags"
    posts }o--|| users : "author"

    posts {
        bigint author_id FK
        text body "nullable"
        bigint category_id FK "nullable"
        timestamp created_at "nullable"
        bigint id PK
        timestamp published_at "nullable"
        varchar title
        timestamp updated_at "nullable"
    }

Every list is sorted: tables, columns, and edges are emitted in the same order on every run. The committed file changes when your schema or your models change, and not otherwise.

What is included

  • One Artisan command, cartographer:erd, with options for seeds, depth, column detail, relation exclusions, format, output path, stdout, and connection.
  • Model discovery across configured directories, including glob patterns for modular and domain-driven layouts.
  • Detection of belongsTo, hasOne, hasMany, belongsToMany, every morph* relation, and the through relations, with an optional strict mode that only inspects methods carrying a Relation return type.
  • Column types normalized across MySQL, PostgreSQL, and SQLite, so the same application produces the same diagram on every driver.
  • Seed models and a hop limit, for cutting a large schema down to one subsystem.
  • Atomic file writing, so an interrupted run never leaves a truncated diagram behind.
  • Markdown output with a mermaid fence, or a raw .mmd file for mmdc and other Mermaid tooling.

What it does not do

The package draws its edges deliberately. What follows describes the shape it sets out to have. Treat none of it as planned work, and none of it as ruled out forever.

  • Parse migration files. Migrations are history. The database structure is the single source of truth, which is why generating a diagram needs a reachable connection.
  • Read table data. No query the package issues touches your rows; introspection reads structure only.
  • Render PNG or SVG. GitHub, GitLab, and mmdc already render the output.
  • Support Laravel 10 or older. Those versions need doctrine/dbal for introspection, which would be a second permanent code path for end-of-life framework versions.
  • Support ORMs other than Eloquent.
  • Add routes, pages, or anything browser-facing. Cartographer is an Artisan command that writes a file.
  • Filter tables by name. Entities come from discovered models, plus the pivot tables their many-to-many relations name. A table with no model behind it never appears.

Design boundaries

Three decisions explain most of the behaviour you will meet.

Relations are resolved, not inferred. Cartographer builds the relation object and asks it for its keys. Building a relation runs no query, but it does mean each model is instantiated and its zero-argument public methods are called. See relationship detection for what that implies for models with side effects.

The database is authoritative for structure. A model whose table does not exist is skipped with a warning rather than drawn from its $fillable. Key markers come from real primary keys, unique indexes, and foreign key constraints, so a schema that declares no foreign keys shows no FK markers.

Output is deterministic, or it is useless. A diagram that reorders itself on every run produces a noisy diff and stops being reviewable. Every collection the package builds is sorted before it is rendered, and the file is replaced through an atomic rename.

Where to go next

Continue with installation and setup, then follow the quick start to generate and commit a first diagram. From there, how a diagram is built explains the pipeline, and scoping a diagram covers cutting a large schema down to something readable.