Laravel Advanced CRUD Generator

Laravel CRUD Generator is a powerful package designed to accelerate backend development. It provides a full suite of
features including Auto-Discovery Routes, Dynamic Database Schema Validation, Bulk Operations, and
Service-Repository Pattern out of the box.
Stop writing repetitive boilerplate code. Just run one command and you are ready to go! 🚀
✨ Features
- ⚡ Rapid Generation: Generate Model, Controller, Service, Factory, Migration, and Unit Test in one command.
- 🛣️ Auto-Discovery Routes: No need to manually define routes in
api.php. Routes are automatically registered
based on your controller.
- 🛡️ Dynamic Validation: Validation rules are automatically generated by inspecting your Database Schema (supports
MySQL & PostgreSQL).
- 📦 Bulk Operations: Built-in support for Bulk Create, Bulk Update, and Bulk Delete in a single atomic transaction.
- mj Service Pattern: Clean architecture separation using Service classes with built-in Hooks (
beforeCreate,
afterCreate, etc).
- 🧪 Ready-to-use Tests: Automatically generates Feature Tests that cover standard CRUD scenarios.
📦 Installation
Requires PHP 8.2+ and Laravel 11+.
composer require adithwidhiantara/crud
🚀 Quick Start
1. Generate CRUD
Run the magic command to generate everything you need:
php artisan make:crud Product
This command will generate:
app/Models/Product.php
app/Http/Controllers/ProductController.php
app/Http/Services/ProductService.php
database/migrations/xxxx_create_products_table.php
database/factories/ProductFactory.php
tests/Feature/ProductControllerTest.php
2. Update Migration
Open the generated migration file and define your table schema:
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description')->nullable();
$table->integer('price')->default(0);
$table->timestamps();
});
3. Migrate & Enjoy
Run the migration and your API is ready!
php artisan migrate
You can now access your API at:
GET /api/products
POST /api/products
GET /api/products/{id}
PUT /api/products/{id}
DELETE /api/products/{id}
POST /api/products/bulk
📖 Deep Dive
🛡️ Dynamic Validation
You don't need to write validation rules manually. The package inspects your database columns to generate rules:
- Type:
varchar(20) → string|max:20
- Nullable:
nullable() → nullable rule.
- Default: Has
default value → Field becomes optional.
- PostgreSQL Support: Fully supports Postgres specific types and length constraints.
If you need custom rules, simply override the rules() method in your Controller's Request class (or creating a custom
Request).
📦 Bulk Operations
The /bulk endpoint allows you to perform multiple operations in a Single Database Transaction.
Endpoint: POST /api/products/bulk
Payload Example:
{
"create": [
{
"name": "Laptop",
"price": 15000000
},
{
"name": "Mouse",
"price": 200000
}
],
"update": {
"10": {
"price": 14500000
},
"12": {
"name": "Gaming Mouse"
}
},
"delete": [
15,
16,
17
]
}
If any operation fails, the entire transaction is rolled back.
⚙️ Model Configuration
Your models (extending CrudModel) have two powerful methods to control the API output and Validation behavior.
-
getShowOnListColumns()
This method is mandatory. It determines which columns are returned when calling the List Endpoint (GET
/api/products). This helps optimize performance by selecting only necessary fields for table views.
-
ignoredColumns()
This method controls the Auto-Validation Generator. By default, the generator ignores system columns (id, created_at,
updated_at, deleted_at).
If you have sensitive columns (like api_token, password_hash, is_admin) or calculated columns that should NOT be
validated or accepted from the Request payload, override this method.
Here is the English translation for your documentation:
🔍 Filtering, Searching & Sorting
This package provides secure and powerful query manipulation features out-of-the-box.
1. Filtering
You can filter results based on specific columns. By default, no columns are filterable for security reasons. You
must allow them in your Model.
In Model (App\Models\Product.php):
public function filterableColumns(): array
{
return ['status', 'category_id', 'price', 'created_at'];
}
API Usage:
-
Exact Match: /api/products?filter[status]=active
-
Query: WHERE products.status = 'active'
-
Multiple Values (IN): /api/products?filter[category_id][]=1&filter[category_id][]=5
-
Query: WHERE products.category_id IN (1, 5)
-
Null Checks: /api/products?filter[deleted_at]=null (or !null)
-
Query: WHERE products.deleted_at IS NULL
Advanced Operators (Range Filtering)
You can use logical operators for range filtering. Supported operators: eq, gt, gte, lt, lte, like,
between.
-
Greater/Less Than: /api/products?filter[price][gte]=1000&filter[price][lte]=5000
-
Query: WHERE products.price >= 1000 AND products.price <= 5000
-
Partial Match (Like): /api/products?filter[sku][like]=INV-2024
-
Query: WHERE products.sku LIKE '%INV-2024%'
-
Date Range (Between): /api/products?filter[created_at][between]=2024-01-01,2024-12-31
-
Query: WHERE products.created_at BETWEEN '2024-01-01' AND '2024-12-31'
Note: All filter columns are automatically qualified with the table name (e.g., products.price) to prevent "
Ambiguous Column" errors during joins.
2. Global Search (Fuzzy)
The search feature allows text searching (LIKE %keyword%) across multiple columns simultaneously using OR logic. It
supports searching within Nested Relationships.
In Model:
public function searchableColumns(): array
{
return [
'name',
'category.name',
'tags.title',
];
}
API Usage:
- Search:
/api/products?search=laptop
- Logic:
AND (products.name LIKE '%laptop%' OR category.name LIKE '%laptop%' ...)
3. Dynamic Sorting
You can sort results dynamically. Define allowed columns in sortableColumns().
In Model:
public function sortableColumns(): array
{
return ['price', 'created_at', 'name'];
}
API Usage:
- Ascending:
/api/products?sort=price
- Descending:
/api/products?sort=-price (Add - prefix)
4. Custom Query (Hook)
Use extendQuery in your Service to add custom logic (scopes, joins, etc.) without overriding the main getAll method.
In Service:
protected function extendQuery(Builder $query): Builder
{
if (!auth()->user()->isAdmin()) {
$query->where('user_id', auth()->id());
}
return $query;
}
The video below explains the common ambiguous column error in Laravel queries, which your new code now prevents.
Resolving the ambiguous column error in your Laravel Eloquent left join query
🏗️ Defining Columns & Relations (Strict Mode)
In BaseCrudService, you are required to define which columns to display by implementing the getShowOnListColumns()
method.
Important: Starting from this version, Strict Mode is enforced. You must define at least one column from the
main table. If you intend to select all columns, you must explicitly specify it as ['*']. The system will throw an
InvalidArgumentException if no local columns are defined to prevent accidental SELECT * queries.
Auto-Load Relations
You can define columns from related tables using the dot-notation format (relation.column). The service will
automatically handle efficient Eager Loading (Partial Select).
Implementation example in your Service:
public function getShowOnListColumns(): array
{
return [
'id',
'title',
'status',
'author.name',
'category.slug',
];
}
🪝 Service Hooks
You can intervene in the CRUD process by overriding hooks in your Service class (
app/Http/Services/ProductService.php).
public function beforeCreateHook(array $data): array
{
$data['slug'] = Str::slug($data['name']);
$data['user_id'] = auth()->id();
return $data;
}
public function afterCreateHook(CrudModel $model): CrudModel
{
Mail::to(auth()->user())->send(new ProductCreated($model));
return $model;
}
🛣️ Custom Endpoints
To add a custom route to your controller that is automatically discovered, use the #[Endpoint] attribute.
use Adithwidhiantara\Crud\Attributes\Endpoint;
class ProductController extends BaseCrudController
{
#[Endpoint(method: 'POST', uri: 'publish/{id}')]
public function publish($id)
{
$this->service()->publish($id);
return response()->json(['message' => 'Published!']);
}
}
Result: POST /api/products/publish/{id}
✅ Testing
The package automatically generates feature tests for your CRUD. To run them:
php artisan test
🚀 Performance
This package is designed for speed. Benchmarks show less than 1ms overhead compared to native Eloquent queries.
See full Benchmark Results.
Ensure you have set up your phpunit.xml or .env.testing database configuration.
License
The MIT License (MIT). Please see License File for more information.