tufikhasan / laravel-crud-generator
Enterprise-grade CRUD generator for Laravel supporting both hybrid (DTO/Action) and simple architecture patterns.
Package info
github.com/tufikhasan/laravel-crud-generator
pkg:composer/tufikhasan/laravel-crud-generator
Requires
- php: ^8.2
- illuminate/console: ^11.0|^12.0|^13.0
- illuminate/support: ^11.0|^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^9.0|^10.0
- phpunit/phpunit: ^10.0|^11.0
README
Generate production-ready, enterprise-grade CRUD scaffolding in seconds — with flexible support for Hybrid, Service, and Repository architectural patterns.
Installation
Composer (Packagist)
composer require tufikhasan/laravel-crud-generator
The package registers itself automatically via Laravel's package auto-discovery.
One command. Thirteen files. Zero boilerplate.
php artisan make:crud Category --api
INFO Generating enterprise CRUD for [Category]...
✓ DTO
✓ Store Action
✓ Update Action
✓ Delete Action
✓ Service
✓ Store Request
✓ Update Request
✓ Admin Controller
✓ API Resource
✓ API Controller
✓ Blade Views (index, create, edit, form)
✓ Routes appended
INFO CRUD for [Category] generated successfully!
API routes: /api/categories
Admin routes: /admin/categories
Route names: admin.categories.{index|create|store|edit|update|destroy}
Next steps:
1. Update your migration in database/migrations/
2. Fill in the $fillable array on the Category model
3. Add fields to the DTO and Service
4. Update validation rules in app/Http/Requests/Category
5. Map fields in the toArray() method of app/Http/Resources/Category/CategoryResource.php
Features
- ✅ Follows SOLID principles — Actions, Services, DTOs, Policies
- ✅ Config-aware paths — customize all output directories
- ✅ Publishable stubs — override any generated file template
- ✅ Model + migration by default — pass
--skip-modelif already exists - ✅ Optional
--apiflag — API controller + Resource + routes - ✅ Optional
--patternoption — Choose betweenservice(default),hybrid, orrepositoryarchitectures - ✅
--forceflag to overwrite existing files - ✅ Individual commands — generate only what you need
- ✅ Auto-registers via Laravel package auto-discovery
- ✅ Works with Laravel 11, 12, and 13
Requirements
| Requirement | Version |
|---|---|
| PHP | ^8.2 |
| Laravel | `^11 |
Quick Start
Generate a full CRUD module
# Admin CRUD only (views + routes + model + migration) php artisan make:crud Product # Admin + API (controller, resource, routes) php artisan make:crud Product --api # Skip model/migration if the model already exists php artisan make:crud Product --skip-model # Generate CRUD using the advanced Hybrid pattern (DTO + Actions) php artisan make:crud Category --pattern=hybrid # Overwrite existing files php artisan make:crud Product --force
Commands Reference
make:crud — Full Scaffolding
php artisan make:crud {name} [--api] [--skip-model] [--view=tailwind|bootstrap] [--force]
| Argument/Option | Description |
|---|---|
name |
Model name in StudlyCase (Category, ProductVariant) |
--api |
Also generate API controller, API resource, and API routes |
--pattern |
Architectural pattern (service, hybrid, or repository, overrides config) |
--skip-model |
Skip model + migration (use when the model already exists) |
--view |
The view framework (tailwind or bootstrap) |
--force |
Overwrite existing files |
Generated files (with --api):
| File | Path |
|---|---|
| Model | app/Models/Category.php |
| Migration | database/migrations/xxxx_create_categories_table.php |
| DTO | app/DTOs/Category/CategoryData.php |
| Store Action | app/Actions/Category/StoreCategoryAction.php |
| Update Action | app/Actions/Category/UpdateCategoryAction.php |
| Delete Action | app/Actions/Category/DeleteCategoryAction.php |
| Service | app/Services/Category/CategoryService.php |
| Store Request | app/Http/Requests/Category/StoreCategoryRequest.php |
| Update Request | app/Http/Requests/Category/UpdateCategoryRequest.php |
| Admin Controller | app/Http/Controllers/Admin/CategoryController.php |
| API Resource | app/Http/Resources/Category/CategoryResource.php |
| API Controller | app/Http/Controllers/Api/CategoryController.php |
| Index View | resources/views/pages/admin/categories/index.blade.php |
| Create View | resources/views/pages/admin/categories/create.blade.php |
| Edit View | resources/views/pages/admin/categories/edit.blade.php |
| Form View | resources/views/pages/admin/categories/form.blade.php |
| Show View | resources/views/pages/admin/categories/show.blade.php |
| Routes | Appended to routes/web.php (and routes/api.php if --api) |
Individual Commands
Use these when you need to generate only a single piece.
make:dto
php artisan make:dto Category
Generates: app/DTOs/Category/CategoryData.php
make:action
php artisan make:action Category store # StoreCategoryAction.php php artisan make:action Category update # UpdateCategoryAction.php php artisan make:action Category delete # DeleteCategoryAction.php
make:crud-service
php artisan make:crud-service Category
Generates: app/Services/Category/CategoryService.php
make:crud-request
php artisan make:crud-request Category store # StoreCategoryRequest.php php artisan make:crud-request Category update # UpdateCategoryRequest.php
make:crud-controller
php artisan make:crud-controller Category admin # Admin/CategoryController.php php artisan make:crud-controller Category api # Api/CategoryController.php
make:crud-resource
php artisan make:crud-resource Category
Generates: app/Http/Resources/Category/CategoryResource.php
make:crud-views
php artisan make:crud-views Category [--view=tailwind|bootstrap]
Generates: resources/views/pages/admin/categories/{index,create,edit,form,show}.blade.php (Using Tailwind or Bootstrap stubs)
make:crud-repository
php artisan make:crud-repository Category
Generates: app/Repositories/Category/CategoryRepository.php
Configuration
Publish the config file to customize all defaults:
php artisan vendor:publish --tag=crud-generator-config
This creates config/crud-generator.php:
return [ // Auto-detected from composer.json. Set to override. 'namespace' => env('CRUD_NAMESPACE', ''), // Output paths, relative to app_path() 'paths' => [ 'dto' => 'DTOs', 'action' => 'Actions', 'service' => 'Services', 'request' => 'Http/Requests', 'controller_admin' => 'Http/Controllers/Admin', 'controller_api' => 'Http/Controllers/Api', 'resource' => 'Http/Resources', 'repository' => 'Repositories', ], // Default Architectural Pattern ('service', 'hybrid', or 'repository') 'pattern' => 'service', // Blade view output path, relative to resource_path('views') 'view_path' => 'pages/admin', // Default View Framework ('tailwind' or 'bootstrap') 'view' => 'tailwind', // View Layout Configuration 'layout' => [ 'type' => 'component', 'name' => 'layouts.dashboard', 'section' => 'content', ], // Route generation settings 'routes' => [ 'web_prefix' => env('CRUD_ROUTE_WEB_PREFIX', null), 'name_prefix' => env('CRUD_ROUTE_NAME_PREFIX', null), 'api_prefix' => env('CRUD_ROUTE_API_PREFIX', ''), ], ];
Configuration Reference
| Key | Default | Description |
|---|---|---|
namespace |
'' (auto) |
App root namespace. Auto-detected if empty. |
paths.dto |
DTOs |
DTO directory relative to app/ |
paths.action |
Actions |
Action directory |
paths.service |
Services |
Service directory |
paths.request |
Http/Requests |
Form Request directory |
paths.controller_admin |
Http/Controllers/Admin |
Admin controller directory |
paths.controller_api |
Http/Controllers/Api |
API controller directory |
paths.resource |
Http/Resources |
API Resource directory |
paths.repository |
Repositories |
Repository directory |
view |
tailwind |
Default view framework (tailwind or bootstrap) |
layout.type |
component |
Layout style (component or extend) |
layout.name |
layouts.dashboard |
Name of the component or layout file |
layout.section |
content |
Name of the section to yield into (if type=extend) |
view_path |
pages/admin |
Relative to resources/views/ |
pattern |
service |
Architectural pattern (service, hybrid, or repository) |
routes.web_prefix |
null |
URL prefix for admin routes (nullable, not required) |
routes.name_prefix |
null |
Named route prefix (nullable, not required) |
routes.api_prefix |
'' |
URL prefix for API routes |
Customizing Stubs
1. Publish Stubs
# Publish stubs only php artisan vendor:publish --tag=crud-generator-stubs # Publish everything (config + stubs) php artisan vendor:publish --tag=crud-generator
Stubs are copied to stubs/crud/ in your project root:
stubs/crud/
├── dto.stub
├── action.store.stub
├── action.update.stub
├── action.delete.stub
├── service.stub
├── service.simple.stub
├── service.repository.stub
├── repository.interface.stub
├── repository.provider.stub
├── repository.stub
├── request.store.stub
├── request.update.stub
├── controller.admin.stub
├── controller.admin.simple.stub
├── controller.admin.repository.stub
├── controller.api.stub
├── controller.api.simple.stub
├── controller.api.repository.stub
├── resource.stub
└── views/
├── tailwind/
│ ├── index.blade.stub
│ ├── create.blade.stub
│ ├── edit.blade.stub
│ ├── form.blade.stub
│ └── show.blade.stub
└── bootstrap/
├── index.blade.stub
├── create.blade.stub
├── edit.blade.stub
├── form.blade.stub
└── show.blade.stub
2. Edit a Stub
The generator always checks your published stubs first, then falls back to the package defaults.
Example — add a Policy check to the generated Store Request:
// stubs/crud/request.store.stub public function authorize(): bool { return $this->user()->can('create', {{ ModelName }}::class); }
3. Available Stub Tokens
Every stub supports these replacement tokens:
| Token | Category → |
|---|---|
{{ ModelName }} |
Category |
{{ modelName }} |
category |
{{ model_name }} |
category |
{{ model-name }} |
category |
{{ ModelNames }} |
Categories |
{{ modelNames }} |
categories |
{{ model_names }} |
categories |
{{ model-names }} |
categories |
{{ RootNamespace }} |
App |
{{ RouteNamePrefix }} |
admin (from config) |
{{ RouteWebPrefix }} |
admin (from config) |
Architecture Overview
This package supports three enterprise-grade architectural patterns. A hybrid approach is recommended for most complex applications, while the service or repository pattern works great for standard entities.
1. Hybrid Pattern (--pattern=hybrid)
The best choice for complex entities (e.g., enterprise multi-vendor eCommerce, SaaS subscriptions, POS, inventory, accounting).
HTTP Request
│
▼
Controller (HTTP only — validate, authorize, build DTO, call Action)
│
▼
Form Request (validation + authorization)
│
▼
DTO (readonly value object — carries validated data)
│
▼
Action (one use-case — wraps service in DB::transaction)
│
▼
Service (reusable business logic — create / update / delete)
│
▼
Model (Eloquent)
2. Service Pattern (Default, or --pattern=service)
Excellent for basic entities like Category, Brand, Unit, Country, City, or Color. It skips the DTO and Action layers entirely.
Request (Validation)
└── Controller
└── Service (Business Logic + Data Access)
└── Model (Eloquent)
3. Repository Pattern (--pattern=repository)
A structured approach that separates data access logic from business logic. It introduces a Repository layer without the overhead of DTOs and Actions.
In true enterprise fashion, this generates both an Interface and a Concrete Implementation, and automatically wires them up via a RepositoryServiceProvider.
Request (Validation)
└── Controller
└── Service (Business Logic)
└── RepositoryInterface (Injected)
└── Repository (Data Access)
└── Model (Eloquent)
Note
The first time you use the repository pattern, the generator creates App\Providers\RepositoryServiceProvider.
Make sure you register this provider in your bootstrap/providers.php or config/app.php!
Example generated DTO
class CategoryData { public function __construct( public readonly string $name, public readonly bool $status, ) {} public static function fromRequest(StoreCategoryRequest|UpdateCategoryRequest $request): self { return new self( name: $request->string('name')->toString(), status: $request->boolean('status'), ); } }
Example generated Action
class StoreCategoryAction { public function __construct( private readonly CategoryService $service, ) {} public function execute(CategoryData $data): Category { return DB::transaction( fn () => $this->service->create($data) ); } }
Users install with:
composer require tufikhasan/laravel-crud-generator
Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-feature - Commit your changes
- Push and open a Pull Request
License
MIT © Towfik Hasan