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

v1.0.1 2025-07-28 05:59 UTC

This package is auto-updated.

Last update: 2025-10-28 06:36:33 UTC


README

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.