Search by

muhammedsalama / crudforge

MuhammedMSalama

Generate production-ready Laravel CRUD modules using clean architecture — models, controllers, services, repositories, requests, resources, factories, tests, translations, and route snippets from a single Artisan command.

Package info

github.com/Muhammed2024Salama/Crud_Forge

pkg:composer/muhammedsalama/crudforge

Statistics

Installs: 4

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v1.2.2 2026-05-16 01:05 UTC

This package is auto-updated.

Last update: 2026-09-16 01:52:57 UTC


README

Latest Version on Packagist Tests PHPStan PHP Version License

Generate production-ready Laravel CRUD modules from a single Artisan command.

Each generated module follows clean architecture — model, API controller, service, repository, interface, form requests, API resource, migration, factory, feature tests, and translations. The generator wires everything automatically: no manual provider registration, no manual route includes, no manual binding setup.

Requirements

Dependency Version
PHP ^8.2
Laravel 11, 12, 13

Note: PHP 8.2 is not compatible with Laravel 13 (which requires PHP ≥ 8.3). The CI matrix enforces this constraint explicitly.

Installation

composer require muhammedsalama/crudforge:^1.2.0

The ^1.2.0 constraint allows any backward-compatible update (1.2.x, 1.3.0, etc.) while blocking major versions that may contain breaking changes. To upgrade to a future major version, review the migration guide in CHANGELOG.md first.

Laravel auto-discovery registers both service providers automatically. No manual registration is required.

Optionally run the install command to publish the config and confirm the setup:

php artisan crudforge:install

Updating the Package

composer update muhammedsalama/crudforge

Patch and minor releases are fully backward-compatible. No changes to your configuration, generated files, or application code are required.

For major version upgrades, see the Upgrade Guide below and the relevant entry in CHANGELOG.md.

Usage

Generate a module

php artisan crudforge:generate Order --fields="customer_name:string,total:decimal,status:boolean,note:text"

That single command:

  1. Generates all files for the Order module
  2. Writes the repository binding to bootstrap/crudforge-bindings.php
  3. Registers the route file in routes/crudforge.php
  4. Reports the live API endpoint

Generated output

app/
├── Http/
│   ├── Controllers/Api/OrderController.php
│   ├── Requests/StoreOrderRequest.php
│   ├── Requests/UpdateOrderRequest.php
│   └── Resources/OrderResource.php
├── Interfaces/
│   └── OrderRepositoryInterface.php
├── Models/
│   └── Order.php
├── Repositories/
│   └── OrderRepository.php
└── Services/
    └── OrderService.php

bootstrap/
└── crudforge-bindings.php  ← updated automatically; commit this file

database/
├── factories/OrderFactory.php
└── migrations/xxxx_xx_xx_create_orders_table.php

lang/
├── en/orders.php
└── ar/orders.php

routes/
├── crudforge-orders.php    ← route definitions for this module
└── crudforge.php           ← route registry; updated automatically, commit this file

tests/
└── Feature/OrderApiTest.php

What is automatic

Step Handled by
Service provider registration Laravel auto-discovery
Hydrating repository bindings at runtime CrudForgeRuntimeServiceProvider
Loading the routes/crudforge.php manifest CrudForgeRuntimeServiceProvider
Writing binding to bootstrap/crudforge-bindings.php crudforge:generate
Registering route in routes/crudforge.php crudforge:generate

bootstrap/providers.php, bootstrap/app.php, and routes/api.php are never modified.

API endpoints

After generating the Order module, the following REST endpoints are available:

GET    /api/orders            Paginated index
POST   /api/orders            Create
GET    /api/orders/{order}    Show
PUT    /api/orders/{order}    Update
DELETE /api/orders/{order}    Destroy

The /api prefix is controlled by crudforge.defaults.route_prefix in the published config. See Configuration.

Supported query parameters on GET /api/orders:

Parameter Description
search Full-text search across string/text fields
sort_by Column name (validated against an allowlist)
sort_direction asc or desc
per_page 1–100, default 15

Field Types

Alias Normalised type Migration column Eloquent cast
string, str, varchar string string() —
text text text()->nullable() —
integer, int integer integer() —
bigInteger, bigint bigInteger bigInteger() —
unsignedInteger, uint unsignedInteger unsignedInteger() —
unsignedBigInteger, ubigint unsignedBigInteger unsignedBigInteger() —
boolean, bool boolean boolean()->default(false) boolean
decimal, float, double decimal decimal(10, 2) decimal:2
date date date()->nullable() date
datetime datetime dateTime()->nullable() datetime
timestamp timestamp timestamp()->nullable() datetime
json, jsonb json json()->nullable() array
foreignId, foreign_id foreignId foreignId()->constrained()->cascadeOnDelete() —

Validation rules are derived automatically from the field type:

  • StoreRequest — required fields use 'required'; nullable types (text, date, datetime, json) use 'nullable'
  • UpdateRequest — all fields use 'sometimes' for safe partial updates

Command Reference

# One-time setup — publishes config and prints a setup summary
php artisan crudforge:install

# Generate a full CRUD module
php artisan crudforge:generate {Name} --fields="field:type,..."

# Preview what would be generated without writing any files
php artisan crudforge:generate {Name} --fields="..." --dry-run

# Overwrite existing files without confirmation
php artisan crudforge:generate {Name} --fields="..." --force

# Skip automatic registry updates (binding + route manifest)
php artisan crudforge:generate {Name} --fields="..." --no-auto-register

# Re-wire a specific module's binding (e.g. after pulling from Git)
php artisan crudforge:install-bindings Order

# Re-wire all modules at once
php artisan crudforge:install-bindings --all

Configuration

Publish the config to customise output paths, namespaces, and runtime defaults:

php artisan vendor:publish --tag=crudforge-config
// config/crudforge.php

'paths' => [
    'models'      => app_path('Models'),
    'controllers' => app_path('Http/Controllers/Api'),
    // ...
],

'namespaces' => [
    'models'      => 'App\\Models',
    'controllers' => 'App\\Http\\Controllers\\Api',
    // ...
],

'defaults' => [
    'pagination_per_page' => 15,

    'route_prefix' => 'api',
],

'auto_register' => true,

Important: If you customise the API route prefix in bootstrap/app.php (e.g. withRouting(apiPrefix: 'v1')), you must set crudforge.defaults.route_prefix to the same value ('v1'). Otherwise generated routes and generated tests will use the wrong prefix.

Publish stubs to customise the generated code templates:

php artisan vendor:publish --tag=crudforge-stubs

Stubs are published to stubs/vendor/crudforge/. CrudForge checks for a published stub before falling back to the built-in one, so you only need to publish the stubs you intend to modify.

Architecture

Every generated module follows a strict layered architecture:

HTTP Request
     │
     ▼
Controller        ← HTTP layer only; no business logic
     │
     ▼
Service           ← Business logic; depends on the interface, not the concrete class
     │
     ▼
RepositoryInterface  ← Contract; makes the concrete class swappable
     │
     ▼
Repository        ← Eloquent queries; implements the interface
     │
     ▼
Model

The generated code has zero runtime dependency on CrudForge. Once generation is complete, the package can be moved to require-dev or removed entirely without affecting the running application.

Database Compatibility

The search logic in generated repositories is driver-aware and inlined — no runtime package dependency:

Driver Operator
MySQL / SQLite LIKE
PostgreSQL ILIKE (case-insensitive)

Extending CrudForge

Tag any GeneratorContract implementation with crudforge.generators in your own service provider to add it to the generation pipeline without modifying the package:

use MuhammedSalama\CrudForge\Contracts\GeneratorContract;

// In your ServiceProvider::register():
$this->app->bind(PolicyGenerator::class);
$this->app->tag([PolicyGenerator::class], 'crudforge.generators');

Your generator runs after the built-in ones on every crudforge:generate call.

Safety

  • Files are never overwritten without confirmation unless --force is passed
  • Declining a single overwrite skips that file and continues the rest of the run
  • All output paths are validated against base_path() to prevent path traversal
  • Model names must match [A-Za-z][A-Za-z0-9]*
  • Field names must match [a-z][a-z0-9_]*

Upgrade Guide

Upgrading from 1.1.x to 1.2.x

1.2.x is a compatibility-only release. No changes to the public API, generated output, or configuration.

composer update muhammedsalama/crudforge

No further action is required.

Upgrading from 1.0.x to 1.1.x

1.1.x introduced the runtime registry system that replaces direct bootstrap/providers.php editing.

Step 1 — Update the package

composer update muhammedsalama/crudforge

Step 2 — Remove any manual CrudForge entries from bootstrap/providers.php

If a previous version added a provider entry for CrudForge to bootstrap/providers.php, remove it. Both providers are now registered via Composer auto-discovery.

Step 3 — Remove manual route includes from routes/api.php

If you previously added require __DIR__.'/crudforge-*.php' lines to routes/api.php, remove them. Routes are now loaded from a single manifest (routes/crudforge.php) by CrudForgeRuntimeServiceProvider.

Step 4 — Regenerate the binding registry

php artisan crudforge:install-bindings --all

This creates bootstrap/crudforge-bindings.php. Commit it to version control.

Step 5 — Clear caches

php artisan config:clear
php artisan route:clear

Troubleshooting

Routes return 404

Generated routes are loaded automatically by the service provider. If you have cached routes, clear the cache:

php artisan route:clear

If you previously added a manual require __DIR__.'/crudforge-*.php' in routes/api.php, remove it — routes are now auto-loaded via routes/crudforge.php and the manual require causes duplicate registration.

If you have changed the API prefix in bootstrap/app.php, ensure crudforge.defaults.route_prefix in your published config matches it.

"Target [Interface] is not instantiable"

The binding registry is missing or incomplete. Re-run the binding setup:

php artisan crudforge:install-bindings --all

Then verify that bootstrap/crudforge-bindings.php exists and contains the expected interface-to-repository mapping. If the file was accidentally deleted or excluded from version control, re-running the above command regenerates it. Ensure the file is committed — it is a CrudForge-owned file, not a Laravel core file.

Config not found / stale

php artisan vendor:publish --tag=crudforge-config
php artisan config:clear

Regenerating an existing module

Use --force to overwrite all files, or omit it to be asked per file:

php artisan crudforge:generate Order --fields="..." --force

Regenerating does not create a duplicate migration file — CrudForge detects the existing migration and overwrites it in place.

Testing

Run the test suite:

composer test

Run static analysis:

composer analyse

Versioning Strategy

This package follows Semantic Versioning (MAJOR.MINOR.PATCH):

Increment When Example
PATCH Bug fixes and internal improvements; no API changes 1.2.0 → 1.2.1
MINOR New features added in a backward-compatible manner 1.2.0 → 1.3.0
MAJOR Breaking changes to the public API or generated output 1.2.0 → 2.0.0

Patch and minor updates are safe to apply via composer update without reviewing generated files or configuration. Major version bumps will always include a migration guide in CHANGELOG.md.

Changelog

See CHANGELOG.md for the full release history.

Contributing

Contributions are welcome. Please open an issue before submitting a pull request for significant changes.

License

The MIT License. See LICENSE.

Support

For support, bug reports, or feature requests:

Acknowledgments

  • Built for Laravel developers who want production-ready CRUD scaffolding
  • Inspired by Laravel clean architecture and modern package development practices
  • Special thanks to all contributors and testers

Related Resources

Made with ❤️ by Muhammed Salama