bishnu/laravel-repository-generator

A Laravel package to generate repositories, interfaces, services, and handling Module-based structure with ease.

Installs: 9

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Forks: 0

pkg:composer/bishnu/laravel-repository-generator

v1.0.4 2026-01-08 07:43 UTC

This package is not auto-updated.

Last update: 2026-02-19 02:31:31 UTC


README

The Ultimate Tool for Laravel APIs

A powerful, production-ready Laravel package that automatically generates Repositories, Services, Controllers, Requests (with auto-validation rules!), Resources, and Routes.

It strictly follows SOLID Principles and Clean Architecture, and includes built-in support for:

  • 🔍 Advanced Filtering & Searching (DataTables ready)
  • 🔒 Role-Based Access Control (Row-level security)
  • 📄 Automatic Pagination & Limiting
  • 📂 Spatie Media Library Integration
  • 🏗️ Laravel Modules (nwidart) support
  • 🔗 Auto-Relationship Loading

🚀 Features at a Glance

FeatureDescription
Instant ScaffoldingCreate Repositories, Interfaces, Controllers, Requests, and Resources in 1 command.
Smart ValidationAutomatically reads your Database Schema to generate validation rules (required, nullable, exists, etc.).
Auto-RoutingAutomatically injects API Resource routes into api.php.
Advanced FilteringFilter by any column, relation, date range, or generic search with ?filters[...].
Role ScopingAdmins see everything; Users see only their own data (automatically enforced).
Media HandlingUpload files, handle replacements, and specialized collections seamlessly.
Flexible IDsChoose between UUIDs or standard IDs; the package auto-detects schema for lookups & relations.

📦 Installation

1. Require the Package

composer require bishnu/laravel-repository-generator

2. Install & Publish Config

php artisan repo:install

3. Enable API Routes (Laravel 11+)

If you are using Laravel 11 or higher and haven't enabled API routes yet, ensure they are registered in bootstrap/app.php:

// bootstrap/app.php
return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        api: __DIR__.'/../routes/api.php', // Add this line
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )

🛠 Usage & Scenarios

1️⃣ Generating a Repository

The command checks your database table columns to generate validation rules automatically.

# Standard Laravel App
php artisan make:repo Product

# For a Specific Module (e.g., Ecommerce)
php artisan make:repo Product --module=Ecommerce

What gets created?

  • ProductRequest: With rules like name => required, category_id => exists:categories,id.
  • ProductResource: Maps your model to JSON (CamelCase by default).
  • ProductRepository: Handles DB logic (pagination, filters, auth).
  • ProductController: Standard CRUD methods.
  • api.php: Injects Route::apiResource('products', ...)

2️⃣ Advanced Filtering (Deep Dive)

To enable advanced filtering, ensure your model extends BaseModel. It already includes the HasFilters trait and other essentials.

// App/Models/Product.php
use Bishnu\RepositoryGenerator\Base\BaseModel;

class Product extends BaseModel
{
    /**
     * Exact match filters
     * Usage: ?filters[status]=active&filters[category_id]=1
     */
    protected $filterable = ['status', 'category_id', 'is_featured'];

    /**
     * Searchable columns (LIKE %query%)
     * Usage: ?filters[search]=macbook
     */
    protected $searchable = ['name', 'description', 'sku', 'vendor.name'];

    /**
     * Relationship filters (Dot notation)
     * Usage: ?filters[category.slug]=electronics
     */
    protected $filterableRelations = ['category', 'vendor', 'tags'];
}

💡 Filter Query Examples

ScenarioAPI Request URL
Multiple ValuesGET /products?filters[status]=active,pending
Range FilterGET /products?filters[price][operator]=>&filters[price][value]=100
Date Range (Preset)GET /products?filters[created_at]=this_week (today, yesterday, last_month, etc.)
Date Range (Custom)GET /products?filters[created_at][from]=2023-01-01&filters[created_at][to]=2023-01-31
Sort By RelationGET /products?sort_by=category.name&sort_direction=desc
Global SearchGET /products?filters[search]=apple (Searches all columns in $searchable)

3️⃣ Eager Loading Relations (?with=)

The package automatically handles eager loading of relationships based on the URL query. This is handled by the HandleRelations trait.

🔹 Usage

You can load relationships (including nested ones) by passing the with parameter in the request.

Example Request:

GET /api/products?with=category,vendor,reviews.user

How it works:

  1. The HandleRelations trait listens to the retrieved event of the model.
  2. It checks for the with query parameter.
  3. It validates that the requested relations exist on the model (to prevent errors).
  4. It loads them automatically before the data reaches your Resource/Controller.

🔹 Support in Resources

When using the generated Resource, these relations are automatically included in the JSON response if they are loaded.

{
  "id": "uuid-1",
  "name": "Macbook Pro",
  "category": {
    "id": "cat-1",
    "name": "Laptops"
  },
  "vendor": {
    "id": "ven-1",
    "name": "Apple"
  }
}

🔹 Customizing the Resource

If you need to add custom fields or conditionally load relations, you can override appendAdditionalRelations or appendedResource in your generated Resource.

// App/Transformers/ProductResource.php
use Bishnu\RepositoryGenerator\Base\BaseJsonResource;

class ProductResource extends BaseJsonResource
{
    /**
     * Define the data structure
     */
    protected function appendedResource($request): array
    {
        return [
            'id'    => $this->uuid,
            'name'  => $this->name,
            'price' => $this->price,
            'is_low_stock' => $this->stock < 10,
        ];
    }

    /**
     * Manually add specific relations
     */
    protected function appendAdditionalRelations(): array
    {
        return [
            'category' => new CategoryResource($this->whenLoaded('category')),
            'tags'     => TagResource::collection($this->whenLoaded('tags')),
        ];
    }
}

4️⃣ Custom Filter Logic (filterCustom)

If the standard filters aren't enough, you can define custom logic in your Model.

// App/Models/Product.php

public function filterCustom($query, $key, $value)
{
    if ($key === 'min_price') {
        $query->where('price', '>=', $value);
        return true; // Stop default processing for this key
    }

    if ($key === 'is_on_sale') {
        $query->whereNotNull('sale_price');
        return true;
    }

    return false; // Let the repository handle other keys
}

5️⃣ Role-Based Access Control (RBAC)

The Repository automatically applies security scopes if the user is NOT an admin.

🔹 Scenario: Permission-Based Visibility

  • Admin: Sees all orders.
  • Manager: Sees orders in their assigned branch_id.
  • User: Sees only their own orders.
// App/Models/Order.php

public function scopeForUser($query, $user)
{
    // 1. Managers see branch orders
    if ($user->hasRole('manager')) {
        return $query->where('branch_id', $user->branch_id);
    }

    // 2. Regular users see their own
    return $query->where('user_id', $user->id);
}

How it works: The repository identifies the user by checking request()->user(). If isAdmin() returns false, it automatically calls forUser($query, $user).

6️⃣ Handling Relationships (Nested Create/Update)

Create or update a Model and its relations in one JSON payload. The BaseModel already includes the logic to handle these relationships.

The Payload:

{
  "name": "New Smartphone",
  "category_id": "uuid-here",
  "relation": {
    "tags": ["uuid-1", "uuid-2"],
    "specifications": {
      "color": "Midnight Black",
      "ram": "12GB"
    },
    "gallery": [
      { "title": "Front View", "sort_order": 1 },
      { "title": "Back View", "sort_order": 2 }
    ]
  }
}

The Model:

use Bishnu\RepositoryGenerator\Base\BaseModel;

class Product extends BaseModel {
    protected static $hasRelations = ['tags', 'specifications', 'gallery'];
}

7️⃣ Media & File Management (Global)

Built on top of Spatie Media Library, with advanced features like global deletion and replacement.

🔹 Uploading Files

Send files via multipart/form-data with the key files or your custom collection name.

🔹 Global Media Deletion

To delete specific media items by their UUID (useful for gallery management):

{
  "clear_media": ["uuid-of-media-1", "uuid-of-media-2"]
}

This works globally on any update/store request.

🔹 Replace Collection

To clear an entire collection (e.g., avatar) and replace with a new one:

{
  "media": {
    "clear": true
  }
}

8️⃣ "How It Works" - A Step-by-Step Example

Let's say you want to build a Blog API.

  1. Create Table: Add a posts table with title, content, user_id.
  2. Run Command: php artisan make:repo Post.
  3. Customize Model:
    • Ensure it extends BaseModel.
    • Define $searchable = ['title'];
    • Add scopeForUser to restrict post editing to owners.
  4. Done!: You now have:
    • GET /api/posts (Filtered, Paginated, Scoped)
    • POST /api/posts (Validated, Auto-UUID generation)
    • PUT /api/posts/{uuid} (Auto-Relation handling)
    • DELETE /api/posts/{uuid}

9️⃣ UUID vs. Standard ID Handling

The package is designed to be identifier-agnostic. You can use standard auto-incrementing IDs, UUIDs, or even a mix of both across different tables.

  • Auto-Detection: The package checks if a uuid column exists in your table. If it does, it uses UUIDs for lookups and relationship resolution. If not, it falls back to standard id.
  • Automatic Generation: If a uuid column exists, the BaseModel automatically generates a UUID upon record creation.
  • Payload Resolution: When you send a nested relationship payload (e.g., category: "some-uuid"), the package automatically resolves it to the correct internal database ID, whether searching by UUID or primary ID.
  • Resource Output: The generated Resource classes automatically map the JSON id property to the model's uuid column if present, otherwise to the standard id.

⚙️ Configuration

The package configuration is located at config/modules.php. You can customize:

  • path: Where modules are stored.
  • namespace: The base namespace for your app.
  • stubs: Override the default templates.

📄 License

MIT License.