Looking to hire Laravel developers? Try LaraJobs

laravel-api-crud maintained by david-chamling

Description
A complete Laravel API CRUD generator with model, controller, service, requests and resources scaffolding
Last update
2025/07/28 07:59 (v1.0.1)
License
Links
Downloads
41

Comments
comments powered by Disqus

Laravel API CRUD Generator – Fast, Flexible, and Extensible API Scaffolding

Laravel PHP GitHub Repo stars

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.