PHPackages                             zuqongtech/laravel-anvil - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. zuqongtech/laravel-anvil

ActiveLibrary[Database &amp; ORM](/categories/database)

zuqongtech/laravel-anvil
========================

Full Laravel project scaffolding via live database introspection — models, controllers, form requests, services, repositories, gates, API routes, factories, seeders, migrations, events, observers, policies, and feature tests generated from your connected database.

v1.0.8(1mo ago)514↓57.1%MITPHPPHP ^8.2

Since Jun 8Pushed 1mo agoCompare

[ Source](https://github.com/gideonzozingao/laravel-anvil)[ Packagist](https://packagist.org/packages/zuqongtech/laravel-anvil)[ RSS](/packages/zuqongtech-laravel-anvil/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (32)Versions (9)Used By (0)

Laravel Anvil
=============

[](#laravel-anvil)

> ⚒ Forge a complete Laravel application from your database.

**Laravel Anvil** introspects a live database and hammers your raw schema into a full, idiomatic Laravel scaffold — models, controllers, API resources, form requests, services, repositories, policies, gates, observers, events, factories, seeders, migrations and tests — plus an optional versioned JSON API, an OpenAPI 3.1 specification with Swagger UI, and a complete web CRUD front end in either **pure Blade + Tailwind** or **Blade + Livewire**.

Point it at a database, run one command, and get working code you own.

Table of contents
-----------------

[](#table-of-contents)

- [Why Anvil](#why-anvil)
- [Requirements](#requirements)
- [Installation](#installation)
- [Quick start](#quick-start)
- [Commands](#commands)
    - [`anvil:generate`](#anvilgenerate)
    - [`anvil:generate-web`](#anvilgenerate-web)
    - [`anvil:docs`](#anvildocs)
- [The web scaffold](#the-web-scaffold)
- [The versioned API scaffold](#the-versioned-api-scaffold)
- [OpenAPI &amp; Swagger UI](#openapi--swagger-ui)
- [Configuration](#configuration)
- [Architecture](#architecture)
- [Extending Anvil](#extending-anvil)
- [Working with legacy schemas](#working-with-legacy-schemas)
- [Security](#security)
- [Contributing](#contributing)
- [License](#license)

Why Anvil
---------

[](#why-anvil)

Most generators work from migrations or hand-written model definitions. Anvil works from the **database itself** — reading columns, types, primary keys, foreign keys, unique constraints, indexes and soft-delete markers directly from the live connection. That makes it equally at home on a greenfield Laravel app and on a pre-existing or framework-foreign database (it has been exercised against schemas that don't follow Laravel conventions — non-`id` primary keys, tables without timestamps, and so on).

The output is plain Laravel code with no runtime dependency on Anvil. Generate it, commit it, edit it freely — Anvil is a build-time tool, not a framework.

Requirements
------------

[](#requirements)

RequirementVersionPHP`^8.3`Laravel`^11.0 || ^12.0``symfony/yaml``^6.0 || ^7.0` (pulled in automatically)Optional, depending on what you generate:

- **Livewire 3** (`livewire/livewire`) — only for `anvil:generate-web --stack=livewire`.
- A supported database driver: **PostgreSQL**, **MySQL/MariaDB**, or **SQLite**.

The generated web scaffold styles itself with **Tailwind CSS via CDN** out of the box, so no front-end build step is required to see it working.

Installation
------------

[](#installation)

```
composer require zuqongtech/laravel-anvil --dev
```

Anvil is intended as a development dependency — it generates code; it does not run in production.

Publish the configuration:

```
php artisan vendor:publish --tag=anvil-config
```

This writes `config/anvil.php`. For the Livewire stack, install Livewire too:

```
composer require livewire/livewire
```

Quick start
-----------

[](#quick-start)

```
# Generate models for every table in the default connection
php artisan anvil:generate

# Generate the full kitchen sink for two tables
php artisan anvil:generate --all --tables=posts --tables=comments

# A versioned JSON API (v1) with an OpenAPI spec + Swagger UI
php artisan anvil:generate --api --openapi --tables=posts
php artisan anvil:docs            # prints the docs URL

# A web CRUD front end (Blade + Tailwind)
php artisan anvil:generate-web --tables=posts

# The same, with Livewire components
php artisan anvil:generate-web --stack=livewire --tables=posts
```

Preview anything without writing files by adding `--dry-run`.

Commands
--------

[](#commands)

Anvil ships three Artisan commands.

### `anvil:generate`

[](#anvilgenerate)

Generates the application scaffold (everything except the web front end, which has its own command). Models are always generated; every other artifact is opt -in via a flag, or all at once with `--all`.

```
php artisan anvil:generate [options]
```

**Artifact flags**

FlagGenerates`--all`Every artifact type below`--models`Eloquent models (always on)`--controllers`Resource controllers`--resources`API resource classes`--observers`Model observers`--policies`Authorization policies`--form-requests``StoreXxx` / `UpdateXxx` form requests`--services`Service classes with lifecycle hooks`--repositories`Repository interface + Eloquent implementation`--gates`Gate definitions appended to your auth provider`--api-routes``apiResource` routes appended to `routes/api.php``--factories`Model factories with Faker-inferred definitions`--seeders`Database seeders`--migrations`Reverse-engineered `Schema::create()` migrations`--events``Created` / `Updated` / `Deleted` event classes`--tests`Feature tests for the CRUD endpoints**API &amp; docs flags**

FlagDescription`--api`Generate a versioned JSON API scaffold with JSON enforcement`--api-version=1`Version for `--api` (accepts `1`, `v1`, `V1`)`--openapi`Generate an OpenAPI 3.1 specification`--openapi-format=yaml``yaml` (default) or `json``--openapi-single-file`Merge schemas + paths into one file`--openapi-ui`Publish a static Swagger UI to `public/docs/`**Targeting &amp; behaviour flags**

FlagDescription`--namespace=App\Models`Namespace for generated models`--connection=`Database connection to introspect`--tables=*`Limit to specific tables (repeatable)`--ignore=*`Exclude specific tables (repeatable)`--only=*`Alias for `--tables``--path=app`Base path for generated models`--force`Overwrite existing files without prompting`--backup`Back up existing files before overwriting`--dry-run`Preview without writing files`--with-phpdoc`Add PHPDoc blocks to models`--with-inverse`Generate inverse relationships`--with-constraints`Embed constraint metadata in model comments`--validate-fk`Validate all foreign-key references`--analyze-constraints`Print a constraint summary before generating`--show-recommendations`Print schema optimisation suggestions> **Note** — files that already exist are skipped unless you pass `--force`. When iterating on a schema, `--force` (optionally with `--backup`) is what you want.

### `anvil:generate-web`

[](#anvilgenerate-web)

Generates a complete web CRUD front end — resource controllers, web routes, and views — for the chosen tables. The web scaffold reuses the same **services** and **form requests** as the rest of the app, so those are generated alongside it.

```
php artisan anvil:generate-web [options]
```

FlagDescription`--stack=blade`Front-end stack: `blade` (Blade + Tailwind) or `livewire` (Blade + Livewire)`--tables=*`Limit to specific tables`--only=*`Alias for `--tables``--ignore=*`Exclude specific tables`--connection=`Database connection to introspect`--namespace=App\Models`Namespace of the models the scaffold references`--path=app`Base path for generated models`--layout=`Blade layout the views should extend (overrides config)`--skip-models`Don't (re)generate models — assume they already exist`--no-inverse`Skip inverse-relationship detection when generating models`--force`Overwrite existing files`--backup`Back up existing files before overwriting`--dry-run`Preview without writing files### `anvil:docs`

[](#anvildocs)

Prints the location of the generated API documentation and reports whether the spec has been generated yet.

```
php artisan anvil:docs            # human-readable summary
php artisan anvil:docs --json     # machine-readable
php artisan anvil:docs --open     # open the docs URL in your browser
```

The web scaffold
----------------

[](#the-web-scaffold)

`anvil:generate-web` produces a full create/read/update/delete UI per resource. Both stacks share the same shell: a generated base layout (`resources/views/layouts/anvil.blade.php`) with a **professional collapsible sidebar** whose links are **discovered at runtime** from your registered web routes — every resource appears automatically and the nav stays correct as you add or remove tables, with no regeneration. The sidebar collapses on desktop (remembered via `localStorage`) and slides in as an overlay on mobile.

### `--stack=blade` (default)

[](#--stackblade-default)

Pure Blade + Tailwind. Per resource:

- `App\Http\Controllers\Web\{Model}Controller` — full resource controller (`index`/`create`/`store`/`show`/`edit`/`update`/`destroy`, plus `restore`/`forceDelete` for soft-delete models), returning Blade views and redirecting with flash messages.
- `Route::resource(...)` in `routes/web.php`, inside a managed middleware group.
- `resources/views/{slug}/` — `index`, `create`, `edit`, `show`, and a shared `_form` partial. Inputs are inferred from column types.

### `--stack=livewire`

[](#--stacklivewire)

Blade + Livewire 3. Requests still flow **controller → Blade view → Livewire component**:

- The controller handles only the GET endpoints (`index`/`create`/`show`/`edit`), each rendering a thin Blade wrapper that mounts a component.
- Routes are restricted to those GET actions (`Route::resource(...)->only([...])`).
- `App\Livewire\{Plural}\{Index, Form, Show}` components (with views under `resources/views/livewire/{slug}/`) handle the listing, the create/update form (validation + persistence via the service), and the detail view. All writes happen in the components.

Both stacks delegate persistence to the generated `Service` classes, so business logic lives in one place regardless of front end.

The versioned API scaffold
--------------------------

[](#the-versioned-api-scaffold)

`--api` generates a versioned, JSON-only API:

- Controllers under `App\Http\Controllers\Api\V{n}\`.
- A `ForceJsonResponse` middleware + `ForceJsonApiServiceProvider` that lock the API's requests and exception responses to JSON.
- Versioned route files under `routes/api/v{n}.php`.
- Form requests and services (implied by `--api`).

```
php artisan anvil:generate --api --api-version=2 --tables=posts
```

OpenAPI &amp; Swagger UI
------------------------

[](#openapi--swagger-ui)

`--openapi` produces an **OpenAPI 3.1** specification under `openapi/`:

- **Split-file mode** (default) — one file per schema and path under `openapi/schemas/` and `openapi/paths/`, stitched together by a root `openapi.yaml` that references them.
- **Single-file mode** (`--openapi-single-file`) — everything inlined into one document.

Interactive docs are served at `/docs` by Anvil's `DocsController`, which bundles the split files into one self-contained document on the fly so Swagger UI resolves every reference. Enable the route in config and visit:

```
http://your-app.test/docs

```

```
php artisan anvil:generate --openapi --force
php artisan anvil:docs
```

> Regenerate with `--force` after schema changes — existing spec files are otherwise left untouched.

Configuration
-------------

[](#configuration)

`config/anvil.php` controls defaults. The most useful keys:

```
return [
    // Models
    'namespace'     => 'App\\Models',
    'target_path'   => 'app',
    'connection'    => null,                 // null = default connection
    'ignore_tables' => ['migrations', 'password_reset_tokens', 'sessions'],

    // Web scaffold
    'web' => [
        'controller_namespace' => 'App\\Http\\Controllers\\Web',
        'route_file'           => 'routes/web.php',
        'middleware'           => ['web', 'auth'],
        'layout'               => 'layouts.anvil',
        'generate_layout'      => true,
        'generate_nav'         => true,
        'livewire' => [
            'namespace' => 'App\\Livewire',
        ],
    ],

    // OpenAPI
    'openapi' => [
        'format'      => 'yaml',             // yaml | json
        'split_files' => true,
        'output_path' => 'openapi',
        'title'       => null,               // defaults to app name
        'api_version' => 'v1',
        'security'    => 'sanctum',          // sanctum | passport | none
        'docs' => [
            'enabled'    => true,
            'route'      => 'docs',
            'middleware' => [],
            'ui_version' => '5.17.14',
        ],
    ],

    // Large-schema safety prompt
    'validation' => [
        'confirm_threshold' => 50,
    ],
];
```

Architecture
------------

[](#architecture)

Anvil is built around a small, explicit pipeline:

- **`Contracts\Generator`** — every generator implements `supports()`, `getName()` and `generate(ModelMetadata, GenerationOptions)`. Generators that need a once-per-run step (e.g. writing the OpenAPI root spec) also expose `finalize()`.
- **`GenerationOptions`** — an immutable DTO carrying every flag through the pipeline, built from the command line, an array, or config defaults.
- **`GenerationOrchestrator`** — resolves the registered generators, runs the per-model pass, then the finalization pass.
- **`RunsGenerationPipeline`** — a trait shared by `anvil:generate` and `anvil:generate-web` so both commands run the identical pipeline and never diverge.
- **`DatabaseInspector` / `ModelMetadata`** — read the schema and normalise it into the metadata every generator consumes.
- **`LaravelAnvilServiceProvider`** — registers the commands and the generator list.

Extending Anvil
---------------

[](#extending-anvil)

Add your own artifact by implementing the contract and registering it:

```
namespace App\Anvil;

use Zuqongtech\LaravelAnvil\Contracts\Generator;
use Zuqongtech\LaravelAnvil\Support\GenerationOptions;
use Zuqongtech\LaravelAnvil\Support\ModelMetadata;

final class SidecarGenerator implements Generator
{
    public function supports(GenerationOptions $options): bool
    {
        return $options->services; // or your own flag
    }

    public function getName(): string
    {
        return 'Sidecar';
    }

    public function generate(ModelMetadata $meta, GenerationOptions $options): array
    {
        // ...write your file, return a result row...
        return [[
            'type'   => $this->getName(),
            'name'   => $meta->model,
            'status' => 'success',
        ]];
    }
}
```

Register it in your own service provider by adding the class to Anvil's generator list. Resolve generators **through the container** (`app()->make()`) rather than `new`, so any constructor dependencies autowire correctly.

Working with legacy schemas
---------------------------

[](#working-with-legacy-schemas)

Anvil aims to be robust against databases that don't follow Laravel conventions:

- **Non-`id` primary keys** — views and route bindings resolve the real key column rather than assuming `id`.
- **Tables without timestamps** — repositories order listings by an existing column (timestamps if present, otherwise the primary key) instead of blindly using `created_at`.
- **Composite / missing keys** — handled gracefully where a single-column key is required.

If you hit a schema shape that isn't handled well, please open an issue with the DDL — these cases are exactly what hardens the tool.

Security
--------

[](#security)

Anvil generates code from database identifiers and serves documentation, so a few notes:

- It is a **development tool**; install it with `--dev` and don't ship it to production.
- Generated code is plain Laravel that you review and own — treat it as your own code for audit purposes.
- The Swagger docs route is configurable; lock it behind middleware (or disable it) for any non-local environment via `anvil.openapi.docs.middleware` / `anvil.openapi.docs.enabled`.
- Recommended companions for auditing generated output: `composer audit`, `roave/security-advisories`, Larastan/PHPStan, and a SAST pass (Psalm taint analysis, Semgrep, or progpilot).

Contributing
------------

[](#contributing)

Issues and pull requests are welcome. Please include the database DDL (or a minimal reproduction) for any generation bug, and run the test suite plus static analysis before submitting.

License
-------

[](#license)

Laravel Anvil is open-source software released under the **MIT License**.

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance91

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

8

Last Release

44d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9c44affc58234ac671f1da503847a5b0af4f152ec300525a4fbd4142cff27b14?d=identicon)[gideongzozingao](/maintainers/gideongzozingao)

---

Top Contributors

[![zuqongtech](https://avatars.githubusercontent.com/u/63514245?v=4)](https://github.com/zuqongtech "zuqongtech (25 commits)")

---

Tags

laravelfactoryscaffoldingdatabasegeneratorscaffoldeloquentserviceboilerplaterepositoryseedercode-generationintrospectionlaravel-anvil

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/zuqongtech-laravel-anvil/health.svg)

```
[![Health](https://phpackages.com/badges/zuqongtech-laravel-anvil/health.svg)](https://phpackages.com/packages/zuqongtech-laravel-anvil)
```

###  Alternatives

[laravel/ai

The official AI SDK for Laravel.

1.0k3.2M246](/packages/laravel-ai)[illuminate/queue

The Illuminate Queue package.

20432.6M1.7k](/packages/illuminate-queue)[flarum/core

Delightfully simple forum software.

211.4M2.4k](/packages/flarum-core)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[itpathsolutions/dbstan

Database Standardization and Analysis Tool for Laravel

463.0k](/packages/itpathsolutions-dbstan)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
