david-chamling / laravel-api-crud
A complete Laravel API CRUD generator with model, controller, service, requests and resources scaffolding
Installs: 33
Dependents: 0
Suggesters: 0
Security: 0
Stars: 11
Watchers: 0
Forks: 2
Open Issues: 0
pkg:composer/david-chamling/laravel-api-crud
Requires
- php: ^8.0
 - laravel/framework: ^9.0|^10.0|^11.0|^12.0
 
Requires (Dev)
- laravel/framework: ^9.0|^10.0|^11.0|^12.0
 - orchestra/testbench: ^7.0
 
README
A powerful Laravel package that generates complete CRUD API scaffolding with a single Artisan command.
π Features
- π§ Single-command CRUD scaffolding
 - π§© Built-in lifecycle hooks (before/after store/update)
 - πͺ Custom route macros
 - π Advanced search and filtering
 - π Pagination support
 - π‘οΈ Request validation
 - π― Resource transformation
 - π€ Automatic user tracking (created_by / updated_by)
 - βοΈ Customizable stubs
 
β Requirements
- PHP >= 8.1
 - Laravel >= 9.x
 
π Learn by Example
Want to see it in action? Check out this step-by-step guide where we build a complete Blog API using this package:
π Read the full step-by-step tutorial on Medium
π¦ Installation
Install via Composer:
composer require david-chamling/laravel-api-crud
(Optional) Publish stub files for customization:
php artisan vendor:publish --tag=crud-stubs
β‘ Basic Usage
Generate full CRUD scaffolding for a model:
php artisan make:crud Product
This will generate:
- Controller
 - Service class
 - Form requests
 - API resource
 - Model
 - Migration
 - Routes
 
Define routes in your routes/api.php:
Route::crudResource('products', ProductController::class);
β Note: The
crudResource()macro is automatically registered by the package.
π Request Validation
For security and data integrity, you must define complete validation rules in your generated request classes.
β οΈ Important: This CRUD system only uses validated data. If you forget to define rules in your request classes, fields like
name,price, etc., will be empty or missing from your controller β even if you pass them in the request.
Define validation rules in your generated request classes:
// StoreProductRequest.php public function rules(): array { return [ 'name' => 'required|string|max:255', 'price' => 'required|numeric|min:0', 'category_id' => 'required|exists:categories,id' ]; }
π§© Model Configuration
Ensure your modelβs $fillable property includes all the fields:
// Product.php protected $fillable = [ 'name', 'price', 'category_id', // Add additional fields here ];
π Generated Endpoints
| Method | Endpoint | Description | 
|---|---|---|
| GET | /products | Paginated list | 
| GET | /products/all | Get all records | 
| GET | /products/count | Count total items | 
| GET | /products/{id} | Get single record | 
| POST | /products | Create new record | 
| PUT | /products/{id} | Update record | 
| DELETE | /products/{id} | Delete record | 
| GET | /products/featured | Custom endpoint | 
π Advanced Query Parameters
Customize search, filters, and pagination in your controller:
protected array $searchableColumns = ['name', 'description']; protected array $searchableRelations = ['category' => ['name']]; protected int $paginationNumber = 15;
Examples:
GET /products?search=keyboard
GET /products?filter[status]=active
GET /products?sort_by=price&sort_order=desc
GET /products?with=category&fields=id,name
GET /products?per_page=20&page=2
πͺ Lifecycle Hooks
Override lifecycle hooks in your custom CRUD service:
public function beforeStore(array $data, Request $request): array { $data['slug'] = Str::slug($data['name']); return $data; } public function afterStore(Model $model, Request $request): void { // sending Notification, Sms, Creating logs, Storing into relational table // example: ActivityLog::create([ 'user_id' => $request->user()->id, 'action' => 'store', 'model_id' => $model->id, 'changes' => $model->getChanges(), ]); if ($model->wasChanged('status')) { Notification::send( $model->assignedUsers, new StatusUpdatedNotification($model) ); } }
π API Responses
Use the built-in response helper for consistency:
use DavidChamling\LaravelApiCrud\Utilities\ApiResponse; return ApiResponse::success($data); // 200 OK return ApiResponse::created($newModel); // 201 Created return ApiResponse::error('Something went wrong'); // 400/500 Error return ApiResponse::validationError($errors); // 422 Unprocessable
π§± Customization
After publishing stubs, you can customize all generated files:
stubs/crud-controller/
βββ controller.stub
βββ model.stub
βββ service.stub
βββ store-request.stub
βββ update-request.stub
βββ resource.stub
Modify these to fit your code style or architecture.
π‘ Example Controller
use DavidChamling\LaravelApiCrud\Controllers\CrudController; use DavidChamling\LaravelApiCrud\Utilities\ApiResponse; class ProductController extends CrudController { protected array $searchableColumns = ['name', 'sku']; protected array $searchableRelations = [ 'category' => ['name'], 'manufacturer' => ['name'], ]; public function __construct() { parent::__construct( model: Product::class, storeRequest: StoreProductRequest::class, updateRequest: UpdateProductRequest::class, simpleResource: ProductResource::class, detailedResource: ProductDetailResource::class, serviceClass: ProductCrudService::class ); } public function featured() { $products = $this->model::featured()->get(); return ApiResponse::success(ProductResource::collection($products)); } }
π οΈ Support
Having issues or suggestions? Open an issue on GitHub:
π GitHub Repository
π License
MIT Licensed. See LICENSE.
π€ Contributing
Pull requests and suggestions are welcome! Feel free to open issues for bugs or enhancements.