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.2(yesterday)01↑2900%MITPHPPHP ^8.2

Since Jun 8Pushed yesterdayCompare

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

READMEChangelogDependencies (16)Versions (3)Used By (0)

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

[](#laravel-anvil)

**Full Laravel scaffold generation via live database introspection.**

[![PHP](https://camo.githubusercontent.com/b80da8ba371446d5bfa2bd4bb37d7e362b8093e7de85b2fb74ea5f515658b13e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d253545382e322d3838393242462e737667)](https://php.net)[![Laravel](https://camo.githubusercontent.com/55896a05c3ec030eaca4695c90eb92a015243408c80c7675f6ffeb3b910d50c0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31312e7825323025374325323031322e782d4646324432302e737667)](https://laravel.com)[![License](https://camo.githubusercontent.com/784362b26e4b3546254f1893e778ba64616e362bd6ac791991d2c9e880a3a64e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e2e737667)](LICENSE.md)[![Packagist](https://camo.githubusercontent.com/51bf073ed2e13e892fb09b416cf4aad5e4a8cd073419d080fc67bccad3699ed6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7a75716f6e67746563682f6c61726176656c2d616e76696c2e737667)](https://packagist.org/packages/zuqongtech/laravel-anvil)

---

Table of Contents
-----------------

[](#table-of-contents)

1. [Introduction](#1-introduction)
2. [Requirements](#2-requirements)
3. [Installation](#3-installation)
4. [Configuration](#4-configuration)
5. [Quick Start](#5-quick-start)
6. [Command Reference](#6-command-reference)
    - 6.1 [Core Flags](#61-core-flags)
    - 6.2 [Artifact Flags](#62-artifact-flags)
    - 6.3 [Versioned API Flag](#63-versioned-api-flag)
    - 6.4 [Behaviour Flags](#64-behaviour-flags)
    - 6.5 [Table Selection Flags](#65-table-selection-flags)
7. [Generated Artifacts](#7-generated-artifacts)
    - 7.1 [Eloquent Models](#71-eloquent-models)
    - 7.2 [Controllers](#72-controllers)
    - 7.3 [API Resources](#73-api-resources)
    - 7.4 [Form Requests](#74-form-requests)
    - 7.5 [Services](#75-services)
    - 7.6 [Repositories](#76-repositories)
    - 7.7 [Policies](#77-policies)
    - 7.8 [Gates](#78-gates)
    - 7.9 [Observers](#79-observers)
    - 7.10 [Events](#710-events)
    - 7.11 [Factories](#711-factories)
    - 7.12 [Seeders](#712-seeders)
    - 7.13 [Migrations](#713-migrations)
    - 7.14 [Feature Tests](#714-feature-tests)
8. [Versioned JSON API Scaffold](#8-versioned-json-api-scaffold)
    - 8.1 [Overview](#81-overview)
    - 8.2 [Directory Structure](#82-directory-structure)
    - 8.3 [ForceJsonResponse Middleware](#83-forcejsonresponse-middleware)
    - 8.4 [ForceJsonApiServiceProvider](#84-forcejsonapiserviceprovider)
    - 8.5 [Versioned Route Files](#85-versioned-route-files)
    - 8.6 [Exception Handling](#86-exception-handling)
    - 8.7 [Multi-version Workflow](#87-multi-version-workflow)
9. [Architecture](#9-architecture)
    - 9.1 [Package Structure](#91-package-structure)
    - 9.2 [Generator Contract](#92-generator-contract)
    - 9.3 [GenerationOrchestrator](#93-generationorchestrator)
    - 9.4 [ModelMetadata DTO](#94-modelmetadata-dto)
    - 9.5 [GenerationOptions DTO](#95-generationoptions-dto)
    - 9.6 [DatabaseInspector](#96-databaseinspector)
    - 9.7 [RelationshipDetector](#97-relationshipdetector)
    - 9.8 [ConstraintAnalyzer](#98-constraintanalyzer)
10. [Database Driver Support](#10-database-driver-support)
11. [Extending Anvil](#11-extending-anvil)
    - 11.1 [Writing a Custom Generator](#111-writing-a-custom-generator)
    - 11.2 [Registering a Custom Generator](#112-registering-a-custom-generator)
    - 11.3 [Lifecycle Hooks](#113-lifecycle-hooks)
    - 11.4 [Custom Model Templates](#114-custom-model-templates)
12. [Schema Analysis Tools](#12-schema-analysis-tools)
13. [Naming Conventions](#13-naming-conventions)
14. [Safety and Idempotency](#14-safety-and-idempotency)
15. [Performance](#15-performance)
16. [Troubleshooting](#16-troubleshooting)
17. [Contributing](#17-contributing)
18. [Changelog](#18-changelog)
19. [License](#19-license)

---

1. Introduction
---------------

[](#1-introduction)

**Laravel Anvil** is a developer-productivity package that introspects a live database and generates a complete, idiomatic Laravel application scaffold from the schema it finds. Instead of hand-authoring boilerplate for every table, Anvil reads your columns, foreign keys, indexes, and constraints once and emits production-ready code across the full application stack.

### What Anvil generates

[](#what-anvil-generates)

ArtifactFlagDescriptionEloquent Model*(always)*PHPDoc, fillable, hidden, casts, relationshipsResource Controller`--controllers`Full CRUD, service-injectedAPI Resource`--resources``JsonResource` with relationship loadingForm Requests`--form-requests`Store + Update with schema-inferred rulesService class`--services`Lifecycle hooks, event dispatchRepository`--repositories`Interface + Eloquent implementation + providerPolicy`--policies`All abilities, ownership detection, auto-registerGates`--gates`Appended to `AuthServiceProvider`Observer`--observers`All lifecycle events, soft-delete hooksDomain Events`--events`Created / Updated / Deleted / RestoredFactory`--factories`Faker-powered, type-inferred definitionsSeeder`--seeders`Environment-aware counts, FK orderingMigration`--migrations`Reverse-engineered `Schema::create()`Feature Tests`--tests`Full CRUD test suite**Versioned JSON API****`--api`**Controllers, routes, ForceJson enforcement### Design principles

[](#design-principles)

- **Zero opinions on your domain** — Anvil emits stubs your team fills in. No hidden logic is injected.
- **Idempotent by default** — Running the command twice produces the same output. Existing files are never silently overwritten unless `--force` is passed.
- **Driver-agnostic** — MySQL, PostgreSQL, SQLite, and SQL Server are all supported with full introspection parity.
- **Layered extensibility** — Every generator implements a two-method contract. Drop in your own generators via config without touching package source.
- **PSR-12 compliant** — All generated code adheres to PSR-12 and is immediately usable with Laravel Pint.

---

2. Requirements
---------------

[](#2-requirements)

DependencyVersionPHP`^8.2`Laravel`^11.0` or `^12.0``illuminate/support``^11.0 | ^12.0``illuminate/database``^11.0 | ^12.0``illuminate/console``^11.0 | ^12.0``illuminate/filesystem``^11.0 | ^12.0`> **Note:** Laravel Anvil requires PHP 8.2+ because it uses readonly constructor properties, named arguments, first-class callables, and `match` expressions extensively throughout its codebase.

---

3. Installation
---------------

[](#3-installation)

### Via Composer

[](#via-composer)

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

> Installing as a `require-dev` dependency is recommended because Anvil is a scaffolding tool that should not be present in production builds.

### Publish the configuration file

[](#publish-the-configuration-file)

```
php artisan vendor:publish --provider="Zuqongtech\LaravelAnvil\LaravelAnvilServiceProvider" --tag="config"
```

This creates `config/anvil.php` in your application. You may also publish the stub templates if you want to customise the generated code shapes:

```
php artisan vendor:publish --provider="Zuqongtech\LaravelAnvil\LaravelAnvilServiceProvider" --tag="stubs"
```

Stubs are placed in `stubs/anvil/` and take precedence over the package-bundled templates.

### Service Provider

[](#service-provider)

In Laravel 11+ with the minimal bootstrap (`bootstrap/app.php`), the service provider is auto-discovered via the `extra.laravel.providers` key in `composer.json` and requires no manual registration.

For Laravel applications using the classic `config/app.php` providers array, add:

```
// config/app.php
'providers' => [
    // ...
    Zuqongtech\LaravelAnvil\LaravelAnvilServiceProvider::class,
],
```

---

4. Configuration
----------------

[](#4-configuration)

All configuration lives in `config/anvil.php`. Every key can be overridden via environment variables, making the package CI-friendly without file edits.

### Core settings

[](#core-settings)

```
// config/anvil.php (excerpt)

// PHP namespace for generated models
'namespace' => env('DB_INTROSPECTION_NAMESPACE', 'App\\Models'),

// Filesystem path relative to base_path() where models are written
'target_path' => env('DB_INTROSPECTION_TARGET_PATH', 'app'),

// Database connection name (null = use application default)
'connection' => env('DB_INTROSPECTION_CONNECTION', null),
```

### Ignored tables

[](#ignored-tables)

Anvil ships with a default ignore list that covers Laravel's own infrastructure tables. Add any application-specific tables you want excluded from generation:

```
'ignore_tables' => [
    'migrations',
    'password_resets',
    'password_reset_tokens',
    'failed_jobs',
    'personal_access_tokens',
    'jobs',
    'job_batches',
    'cache',
    'cache_locks',
    'sessions',
    // Telescope, Pulse tables ...
],
```

Pattern-based ignoring is also supported:

```
'ignore_table_patterns' => [
    '/^temp_/',     // Ignore all tables prefixed with "temp_"
    '/^backup_/',   // Ignore all tables prefixed with "backup_"
    '/^_.*/',       // Ignore tables prefixed with an underscore
],
```

### Relationship detection

[](#relationship-detection)

```
'relationships' => [
    'detect_belongs_to'      => true,   // Infer belongsTo from FK columns
    'detect_has_many'        => true,   // Generate inverse hasMany
    'detect_many_to_many'    => true,   // Detect pivot tables
    'detect_polymorphic'     => true,   // Detect *_type / *_id pairs
    'validate_foreign_keys'  => false,  // Fail on broken FK references
    'smart_inverse_detection'=> true,
    'typed_relationships'    => true,
    'max_relationship_depth' => 3,
],
```

### Naming conventions

[](#naming-conventions)

```
'naming' => [
    'singular_models'      => true,   // "users" table → "User" model
    'studly_case_models'   => true,
    'camel_case_relationships' => true,
    'pivot_model_suffix'   => 'Pivot',
    'custom_model_names'   => [
        // Override the default table-to-model conversion for specific tables
        // 'user_data' => 'User',
    ],
],
```

### Fillable strategy

[](#fillable-strategy)

```
'fillable' => [
    // "auto"   = compute from columns (exclude PK, timestamps, hidden)
    // "all"    = mass-assign everything
    // "none"   = emit an empty $fillable array
    'strategy'               => env('DB_INTROSPECTION_FILLABLE_STRATEGY', 'auto'),
    'exclude'                => ['id', 'created_at', 'updated_at', 'deleted_at'],
    'use_guarded_when_efficient' => true,
    'guarded_threshold'      => 0.8,  // Switch to $guarded when >80% fillable
],
```

### Versioned API settings

[](#versioned-api-settings)

```
'api_version'    => env('DB_INTROSPECTION_API_VERSION', 'v1'),
'api_middleware' => ['auth:sanctum'],
```

The `api_middleware` array controls the middleware stack applied to every versioned route group generated by `--api`. Add or remove entries to match your authentication layer.

### Per-generator configuration

[](#per-generator-configuration)

Each generator has its own configuration section under `generators`:

```
'generators' => [

    'controllers' => [
        'namespace'              => 'App\\Http\\Controllers',
        'base_controller'        => 'App\\Http\\Controllers\\Controller',
        'use_resource_controllers' => true,
        'include_validation'     => true,
    ],

    'resources' => [
        'namespace'              => 'App\\Http\\Resources',
        'exclude_fields'         => ['password', 'remember_token', 'api_token', 'secret'],
        'include_relationships'  => true,
    ],

    'form_requests' => [
        'namespace'              => 'App\\Http\\Requests',
        'authorize_returns'      => true,
    ],

    'services' => [
        'namespace'              => 'App\\Services',
        'dispatch_events'        => true,
    ],

    'repositories' => [
        'namespace'              => 'App\\Repositories',
        'interface_namespace'    => 'App\\Repositories\\Contracts',
        'register_provider'      => true,
    ],

    'policies' => [
        'namespace'              => 'App\\Policies',
        'auto_register'          => false,
        'detect_ownership'       => true,
        'ownership_column'       => 'user_id',
    ],

    'observers' => [
        'namespace'              => 'App\\Observers',
        'auto_register'          => false,
        'include_soft_delete_events' => true,
    ],

    'factories' => [
        'namespace'              => 'Database\\Factories',
        'nullable_probability'   => 0.8,
    ],

    'seeders' => [
        'namespace'              => 'Database\\Seeders',
        'dev_count'              => 50,
        'staging_count'          => 10,
        'production_count'       => 0,
        'register_in_db_seeder'  => true,
    ],

    'tests' => [
        'namespace'              => 'Tests\\Feature',
        'use_pest'               => false,
        'auth_guard'             => 'sanctum',
    ],
],
```

### Advanced features

[](#advanced-features)

```
'advanced' => [
    'generate_events'      => false,
    'generate_observers'   => false,
    'generate_collections' => false,
    'generate_resources'   => false,
    'generate_requests'    => false,
    'generate_scopes'      => false,
    'generate_traits'      => false,
    'use_attributes'       => false,  // Requires PHP 8.0+
    'generate_enums'       => false,  // Requires PHP 8.1+
],
```

### Custom type and cast mappings

[](#custom-type-and-cast-mappings)

Override how database column types are mapped to PHP types and Laravel cast strings:

```
'type_mappings' => [
    // 'geometry' => 'string',
    // 'point'    => 'array',
],

'cast_mappings' => [
    // 'geometry' => 'string',
],
```

---

5. Quick Start
--------------

[](#5-quick-start)

### Generate models only

[](#generate-models-only)

```
php artisan anvil:generate
```

Introspects the default database connection, skips the tables in `ignore_tables`, and writes one Eloquent model per table to `app/Models/`.

### Generate the full application scaffold

[](#generate-the-full-application-scaffold)

```
php artisan anvil:generate --all
```

Generates every artifact type for every table in one pass.

### Generate a versioned JSON API

[](#generate-a-versioned-json-api)

```
php artisan anvil:generate --api --api-version=1
```

Produces versioned controllers under `App\Http\Controllers\Api\V1\`, a dedicated route file at `routes/api/v1.php`, and the `ForceJsonApiServiceProvider` that locks all requests and exceptions in that route group to JSON.

### Target specific tables

[](#target-specific-tables)

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

### Preview without writing files

[](#preview-without-writing-files)

```
php artisan anvil:generate --all --dry-run
```

### Using a non-default database connection

[](#using-a-non-default-database-connection)

```
php artisan anvil:generate --connection=reporting --all
```

---

6. Command Reference
--------------------

[](#6-command-reference)

```
php artisan anvil:generate [options]

```

### 6.1 Core Flags

[](#61-core-flags)

FlagDescription`--all`Activate every artifact generator for every table. Equivalent to passing all individual artifact flags simultaneously.`--models`Models are always generated. This flag is accepted for explicitness but has no effect.### 6.2 Artifact Flags

[](#62-artifact-flags)

FlagGenerated files`--controllers``app/Http/Controllers/{Model}Controller.php``--resources``app/Http/Resources/{Model}Resource.php``--form-requests``app/Http/Requests/Store{Model}Request.php`, `Update{Model}Request.php``--services``app/Services/{Model}Service.php``--repositories``app/Repositories/{Model}Repository.php`, `app/Repositories/Contracts/{Model}RepositoryInterface.php`, `app/Providers/RepositoryServiceProvider.php``--policies``app/Policies/{Model}Policy.php``--gates`Appended to `app/Providers/AuthServiceProvider.php``--observers``app/Observers/{Model}Observer.php``--events``app/Events/{Model}Created.php`, `{Model}Updated.php`, `{Model}Deleted.php` (+ `{Model}Restored.php` for soft-delete models)`--factories``database/factories/{Model}Factory.php``--seeders``database/seeders/{Model}Seeder.php``--migrations``database/migrations/{timestamp}_create_{table}_table.php``--api-routes`Appended to `routes/api.php` (legacy mode)`--tests``tests/Feature/{Model}Test.php`### 6.3 Versioned API Flag

[](#63-versioned-api-flag)

FlagDefaultDescription`--api`—Activate the versioned JSON API scaffold. Supersedes `--controllers` and `--api-routes` when set. Automatically implies `--form-requests`, `--services`, `--api-routes`, and `--tests`.`--api-version=N``1`The version number for the scaffold. Accepts bare integers (`1`, `2`) or `v`-prefixed strings (`v1`, `v2`). Controls the `V{N}` directory segment and `v{n}` route prefix.> When `--api` is active, standard `--controllers` output is suppressed — versioned API controllers are generated instead. All other non-controller flags continue to operate independently.

### 6.4 Behaviour Flags

[](#64-behaviour-flags)

FlagDefaultDescription`--force`offOverwrite existing files without prompting.`--backup`offBefore overwriting, copy the existing file to `{filename}.backup.{YmdHis}`.`--dry-run`offPrint all planned actions to the console without writing any files.`--with-phpdoc`onEmit `@property` and `@method` PHPDoc blocks on model classes.`--with-inverse`onDetect tables that reference the current table and generate `hasMany`/`hasOne` methods.`--with-constraints`offEmbed a structured constraint comment block inside every model.`--validate-fk`offAfter inspecting the schema, verify that every FK column references an existing table and column. Emits warnings rather than aborting.`--analyze-constraints`offPrint a constraint summary (PK counts, FK counts, indexes, unique constraints) before generation begins.`--show-recommendations`offAfter generation, print schema optimisation suggestions (missing indexes on FK columns, redundant indexes, nullable FKs, etc.).### 6.5 Table Selection Flags

[](#65-table-selection-flags)

FlagDescription`--tables=TABLE`Process only the named tables. Repeatable: `--tables=posts --tables=comments`.`--only=TABLE`Alias for `--tables`.`--ignore=TABLE`Exclude specific tables in addition to those in `config/anvil.php`. Repeatable.`--namespace=NS`Override the model namespace for this run. Default: `App\Models`.`--path=PATH`Override the target filesystem path for this run. Default: `app`.`--connection=NAME`Use a named database connection defined in `config/database.php`.---

7. Generated Artifacts
----------------------

[](#7-generated-artifacts)

### 7.1 Eloquent Models

[](#71-eloquent-models)

Every table that is not in the ignore list produces one Eloquent model.

**What is detected automatically:**

Schema featureGenerated codeNon-standard primary key name`protected $primaryKey = 'custom_id';`Composite primary key`protected $primaryKey = ['key1', 'key2'];` + `$incrementing = false`UUID primary key`$incrementing = false` + `$keyType = 'string'`Missing `created_at` / `updated_at``public $timestamps = false;``deleted_at` column`use SoftDeletes;` trait`password`, `remember_token` columnsAdded to `$hidden`Boolean, integer, decimal, date, datetime, json columnsAdded to `$casts`Foreign key columns`belongsTo()` relationship methodTables referencing this table`hasMany()` relationship method (with `--with-inverse`)Pivot tables (two FKs, minimal extra columns)`belongsToMany()` (detected by `RelationshipDetector`)`*_type` / `*_id` column pairsPolymorphic relationship stubs**Example output:**

```
