cuongnx/laravel-repo-service-generator

Generate repository-service structure for Laravel with interface and binding

Maintainers

Package info

github.com/xuancuong220691/laravel-repo-service-generator

pkg:composer/cuongnx/laravel-repo-service-generator

Statistics

Installs: 71

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v3.0.0 2026-04-24 14:43 UTC

This package is auto-updated.

Last update: 2026-04-24 14:45:50 UTC


README

โœ… Generate clean Repository-Service structure with interfaces, bindings, and optional MongoDB support for Laravel 11 and 12+

This library provides a powerful artisan command set to generate and manage Repository-Service architecture with optional binding, base classes, and multi-model support. It helps you follow a clean, testable architecture in Laravel projects.

๐Ÿงพ Version Information

Library Version v1.1.0
Laravel ^11.0, ^12.0
PHP Version >= 8.1
MongoDB Support Optional (--type=m) via mongodb/laravel-mongodb

๐Ÿ“š Table of Contents

โš™๏ธ Features

  • Generate Repository, Service, Interface automatically.
  • Optional Model generation (Eloquent or MongoDB).
  • Auto-bind/unbind to AppServiceProvider.
  • Subdirectory/nested folder support (e.g. Pay/Transaction).
  • Generate App-level base classes for easy extension.
  • transaction() support via DB facade.
  • Reversible file generation (remove struct).
  • Fast CLI operations.

โš™๏ธ Installation

composer require cuongnx/laravel-repo-service-generator

๐Ÿ“ฆ For MongoDB support:

composer require mongodb/laravel-mongodb

๐Ÿ—๏ธ Generate Base Classes

php artisan cuongnx:make-base

Generates App-level base classes that extend the library's base classes, so you can add custom methods or override behavior without modifying the vendor code.

Options:

Flag Description
--f, --force Overwrite existing files

Generated files:

app/
โ”œโ”€โ”€ Repositories/
โ”‚   โ”œโ”€โ”€ Contracts/
โ”‚   โ”‚   โ””โ”€โ”€ BaseRepositoryInterface.php   โ† extends lib BaseRepositoryInterface
โ”‚   โ””โ”€โ”€ Eloquent/
โ”‚       โ””โ”€โ”€ BaseRepository.php            โ† extends lib BaseRepository
โ””โ”€โ”€ Services/
    โ”œโ”€โ”€ Contracts/
    โ”‚   โ””โ”€โ”€ BaseServiceInterface.php      โ† extends lib BaseServiceInterface
    โ””โ”€โ”€ BaseService.php                   โ† extends lib BaseService

Once these files exist, all subsequently generated repositories and services will automatically extend your App-level base instead of the library's base. This allows you to add shared methods across your entire project.

โš ๏ธ Run cuongnx:make-base before generating your first struct for best results.

๐Ÿงฑ Create Full Structure (Model + Repo + Service)

php artisan cuongnx:make-struct Post

Options:

Flag Description
--model, --m Also generate the model class
--type= Model type: d = Eloquent (default), m = MongoDB
--no-bind Skip automatic binding in AppServiceProvider
--f, --force Overwrite existing files

๐Ÿ“Œ Example with MongoDB:

php artisan cuongnx:make-struct Product --m --type=m

This command generates the following files:

app/
โ”œโ”€โ”€ Models/
โ”‚   โ””โ”€โ”€ Post.php
โ”œโ”€โ”€ Repositories/
โ”‚   โ”œโ”€โ”€ Contracts/
โ”‚   โ”‚   โ””โ”€โ”€ PostRepositoryInterface.php
โ”‚   โ””โ”€โ”€ Eloquent/
โ”‚       โ””โ”€โ”€ PostRepository.php
โ””โ”€โ”€ Services/
    โ”œโ”€โ”€ Contracts/
    โ”‚   โ””โ”€โ”€ PostServiceInterface.php
    โ””โ”€โ”€ PostService.php

๐Ÿ“Œ If --no-bind is not provided, the following bindings will be added to AppServiceProvider:

$this->app->bind(
    \App\Repositories\Contracts\PostRepositoryInterface::class,
    \App\Repositories\Eloquent\PostRepository::class
);

$this->app->bind(
    \App\Services\Contracts\PostServiceInterface::class,
    \App\Services\PostService::class
);

๐Ÿงฑ Create Simple Service & Interface

Creates a standalone service without a repository โ€” useful for business logic that doesn't need direct database access.

php artisan cuongnx:make-service Custom

Options:

Flag Description
--no-bind Skip automatic binding in AppServiceProvider
--f, --force Overwrite existing files

Generated files:

app/
โ””โ”€โ”€ Services/
    โ”œโ”€โ”€ Contracts/
    โ”‚   โ””โ”€โ”€ CustomServiceInterface.php
    โ””โ”€โ”€ CustomService.php

๐Ÿ”Œ Bindings

Bind both repository & service:

php artisan cuongnx:bind-model User

Options:

Flag Description
--only=repo Bind only repository
--only=service Bind only service

Bind individually:

php artisan cuongnx:bind-repo User
php artisan cuongnx:bind-service User

โŒ Unbind Bindings

php artisan cuongnx:unbind-model User

Options:

Flag Description
--only=repo Unbind only repository
--only=service Unbind only service

Or directly:

php artisan cuongnx:unbind-repo User
php artisan cuongnx:unbind-service User

๐Ÿงน Remove Structures

Remove all generated files (repo + service + optional model):

php artisan cuongnx:remove-struct Post --model

Options:

Flag Description
--model, -m Also remove model
--no-unbind Do not unbind from AppServiceProvider

Remove only service:

php artisan cuongnx:remove-service Post

๐Ÿ“‚ Subdirectory Support

All commands support nested folder structure using / as separator. This is useful for grouping related models under a domain or module.

php artisan cuongnx:make-struct Pay/Transaction --m
php artisan cuongnx:make-service Pay/Notification
php artisan cuongnx:bind-model Pay/Transaction
php artisan cuongnx:unbind-model Pay/Transaction
php artisan cuongnx:remove-struct Pay/Transaction

For Pay/Transaction, the generated structure is:

app/
โ”œโ”€โ”€ Models/
โ”‚   โ””โ”€โ”€ Pay/
โ”‚       โ””โ”€โ”€ Transaction.php
โ”œโ”€โ”€ Repositories/
โ”‚   โ”œโ”€โ”€ Contracts/
โ”‚   โ”‚   โ””โ”€โ”€ Pay/
โ”‚   โ”‚       โ””โ”€โ”€ TransactionRepositoryInterface.php
โ”‚   โ””โ”€โ”€ Eloquent/
โ”‚       โ””โ”€โ”€ Pay/
โ”‚           โ””โ”€โ”€ TransactionRepository.php
โ””โ”€โ”€ Services/
    โ”œโ”€โ”€ Contracts/
    โ”‚   โ””โ”€โ”€ Pay/
    โ”‚       โ””โ”€โ”€ TransactionServiceInterface.php
    โ””โ”€โ”€ Pay/
        โ””โ”€โ”€ TransactionService.php

Bindings use the full namespaced class:

$this->app->bind(
    \App\Repositories\Contracts\Pay\TransactionRepositoryInterface::class,
    \App\Repositories\Eloquent\Pay\TransactionRepository::class
);

Supports any depth: Pay/Gateway/Transaction, Admin/Report/Monthly, etc.

๐Ÿ—„๏ธ BaseRepository Methods

All repositories extend BaseRepository and automatically gain access to these common data methods.

๐Ÿ” Read Methods

Method Description
getAll(array $relations = [], array|string|null $orderBy = null) Get all records with optional relationships and ordering
get(?array $fields = null, array $relations = [], array|string|null $orderBy = null) Get records with selected fields, relationships, and ordering
find($id, ?array $fields = null, array $relations = [], array|string|null $orderBy = null) Find by ID with optional field selection and relationships
findBy(string $key, $value, ?array $fields = null, array $relations = [], array|string|null $orderBy = null) Find a single record by key-value
findByAttributes(array $conditions, ?array $fields = null, array $relations = [], array|string|null $orderBy = null) Find a single record by multiple attributes
getBy(string $key, $value, ?array $fields = null, array $relations = [], array|string|null $orderBy = null) Get multiple records by key-value
getByAttributes(array $conditions, ?array $fields = null, array $relations = [], array|string|null $orderBy = null) Get multiple records by attributes
withTrashed(array $conditions = [], ?array $fields = null, array $relations = []) Get including soft-deleted records (model must use SoftDeletes)
onlyTrashed(array $conditions = [], ?array $fields = null, array $relations = []) Get only soft-deleted records (model must use SoftDeletes)

๐Ÿ“Š Pagination

Method Description
paginate(int $perPage = 15, array $conditions = [], ?array $fields = null, array $relations = [], array|string|null $orderBy = null) Laravel paginated list with filters and relationships
paginateCustom(array $conditions = [], ?array $fields = null, array $relations = [], array|string|null $orderBy = null, int $page = 1, int $limit = 10): array Custom pagination returning ['data', 'current_page', 'per_page', 'total', 'last_page']

๐Ÿ“ˆ Aggregate Methods

Method Description
countBy(array $conditions = []): int Count records by conditions
sum(string $column, array $conditions = []): float|int Sum a column
avg(string $column, array $conditions = []): ?float Average of a column
max(string $column, array $conditions = []): float|int|null Maximum value of a column
min(string $column, array $conditions = []): float|int|null Minimum value of a column

๐Ÿ”ง Utility Methods

Method Description
pluck(string $column, ?string $key = null, array $conditions = []) Pluck values from a column
chunk(int $count, callable $callback, array $conditions = []): bool Process records in chunks; callback returning false stops iteration
increment(string $column, int $amount = 1, array $conditions = [], array $extra = []): int Increment column value
decrement(string $column, int $amount = 1, array $conditions = [], array $extra = []): int Decrement column value
transaction(callable $callback): mixed Run a callable inside a database transaction

โœ… Existence Checks

Method Description
existsBy(string $field, $value): bool Check if a value exists for a field
existsByAttributes(array $conditions): bool Check existence by multiple attributes

๐Ÿ“ Create/Update Methods

Method Description
create(array $data) Create a new record
update($id, array $data) Update by ID
updateFields($model, array $fields, array $except = []) Update specific fillable fields on a model instance
firstOrCreate(array $attributes, array $values = [], array $relations = []) Find or create; returns [Model, bool $wasCreated]
firstOrNew(array $attributes, array $values = [], array $relations = []) Find or instantiate without saving; returns [Model, bool $isNew]
createOrUpdate(array $attributes, array $values = [], ?array $checkFields = null): array Create or update with field tracking; returns [Model, bool $wasCreated, bool $wasUpdated, array $changedFields]
updateOrCreate(array $attributes, array $values = [], array $relations = []) Find and update or create; returns [Model, bool $wasCreated]

โŒ Delete / Restore Methods

Method Description
delete($id) Soft delete by ID
deleteBy(array $conditions): int Delete by conditions, returns number of deleted records
restore($id): bool Restore soft-deleted record
forceDelete($id): bool Permanently delete record

๐Ÿง  BaseService Methods

All services extend BaseService and delegate every method to the underlying repository. The service layer is where you implement business logic on top of the repository.

BaseService exposes the same interface as BaseRepository โ€” all read, write, aggregate, pagination, and utility methods are available. Additional service-level methods:

Method Description
transaction(callable $callback): mixed Run a callable inside a database transaction (delegates to repository)

To add custom business logic, define methods in your generated service class:

class PostService extends BaseService implements PostServiceInterface
{
    public function publish(int $id): bool
    {
        return $this->transaction(function () use ($id) {
            return $this->update($id, ['status' => 'published', 'published_at' => now()]);
        });
    }
}

๐Ÿ” Advanced Query Conditions

The BaseRepository supports flexible query conditions for both Eloquent and MongoDB.

1๏ธโƒฃ Simple Conditions

$conditions = [
    'status' => 'active',
    'user_id' => 123
];

$posts = $postRepo->getByAttributes($conditions);

2๏ธโƒฃ Comparison Operators

$conditions = [
    'price' => ['>=', 100],
    'stock' => ['<', 50],
    'rating' => ['>', 4.5]
];

$products = $productRepo->getByAttributes($conditions);

3๏ธโƒฃ MongoDB Operators

// Using MongoDB $gte, $lte operators
$conditions = [
    'expired_at' => [
        '$gte' => now(),
        '$lte' => now()->addDays(30)
    ]
];

// Using MongoDB $elemMatch for array fields
$conditions = [
    'tags' => [
        '$elemMatch' => ['name' => 'Laravel', 'type' => 'framework']
    ]
];

4๏ธโƒฃ Range Queries

// Using from/to syntax
$conditions = [
    'created_at' => [
        'from' => now()->subDays(7),
        'to' => now()
    ]
];

// Using min/max syntax
$conditions = [
    'price' => [
        'min' => 100,
        'max' => 1000
    ]
];

// Using between operator
$conditions = [
    'age' => ['between', [18, 65]]
];

Both from/to and min/max use whereBetween() internally.

5๏ธโƒฃ IN / NOT IN Queries

$conditions = [
    'status' => ['in', ['active', 'pending', 'processing']],
    'category_id' => ['not_in', [5, 10, 15]]
];

6๏ธโƒฃ NULL Checks

$conditions = [
    'deleted_at' => ['null'],
    'email_verified_at' => ['not_null']
];

7๏ธโƒฃ OR Groups

Use the 'or' key to group conditions with OR logic:

$conditions = [
    'status' => 'active',
    'or' => [
        ['role' => 'admin'],
        ['role' => 'moderator', 'verified' => true],
    ]
];
// WHERE status = 'active' AND (role = 'admin' OR (role = 'moderator' AND verified = 1))

8๏ธโƒฃ Combined Complex Queries

$conditions = [
    'status' => 'active',
    'price' => [
        '$gte' => 100,
        '$lte' => 1000
    ],
    'category_id' => ['in', [1, 2, 3]],
    'created_at' => [
        'from' => now()->subMonth(),
        'to' => now()
    ],
    'tags' => [
        '$elemMatch' => ['featured' => true]
    ]
];

$products = $productRepo->getByAttributes(
    conditions: $conditions,
    fields: ['id', 'name', 'price'],
    relations: ['category', 'images'],
    orderBy: ['created_at' => 'desc']
);

9๏ธโƒฃ Ordering Results

// Simple string (defaults to asc)
$orderBy = 'created_at';

// Single indexed field (defaults to asc)
$orderBy = ['created_at'];

// Associative array
$orderBy = ['created_at' => 'desc'];

// Multiple fields
$orderBy = [
    'status' => 'asc',
    'created_at' => 'desc'
];

// Indexed array of tuples
$orderBy = [
    ['status', 'asc'],
    ['created_at', 'desc']
];

Real-World Examples

Get Active Products Expiring Soon

$products = $productRepo->getByAttributes([
    'status' => 'active',
    'expired_at' => [
        '$gte' => now(),
        '$lte' => now()->addDays(30)
    ]
], orderBy: ['expired_at' => 'asc']);

Get Orders from Last Month in Price Range

$orders = $orderRepo->getByAttributes([
    'total_amount' => [
        'min' => 1000,
        'max' => 5000
    ],
    'created_at' => [
        'from' => now()->subMonth()->startOfMonth(),
        'to' => now()->subMonth()->endOfMonth()
    ],
    'status' => ['in', ['completed', 'shipped']]
], relations: ['user', 'items']);

Process Large Dataset in Chunks

$stopped = $userRepo->chunk(200, function ($users) {
    foreach ($users as $user) {
        if ($user->shouldStop()) {
            return false; // stops chunking, chunk() returns false
        }
        // process...
    }
});

Run Operations in a Transaction

$result = $orderService->transaction(function () use ($data) {
    $order = $this->create($data['order']);
    $this->getRepository()->deleteBy(['cart_id' => $data['cart_id']]);
    return $order;
});

๐Ÿ“ Folder Structure

app/
โ”œโ”€โ”€ Repositories/
โ”‚   โ”œโ”€โ”€ Contracts/
โ”‚   โ”‚   โ”œโ”€โ”€ BaseRepositoryInterface.php     โ† generated by make-base
โ”‚   โ”‚   โ”œโ”€โ”€ UserRepositoryInterface.php
โ”‚   โ”‚   โ””โ”€โ”€ PostRepositoryInterface.php
โ”‚   โ””โ”€โ”€ Eloquent/
โ”‚       โ”œโ”€โ”€ BaseRepository.php              โ† generated by make-base
โ”‚       โ”œโ”€โ”€ UserRepository.php
โ”‚       โ””โ”€โ”€ PostRepository.php
โ”œโ”€โ”€ Services/
โ”‚   โ”œโ”€โ”€ Contracts/
โ”‚   โ”‚   โ”œโ”€โ”€ BaseServiceInterface.php        โ† generated by make-base
โ”‚   โ”‚   โ”œโ”€โ”€ CustomServiceInterface.php
โ”‚   โ”‚   โ”œโ”€โ”€ UserServiceInterface.php
โ”‚   โ”‚   โ””โ”€โ”€ PostServiceInterface.php
โ”‚   โ”œโ”€โ”€ BaseService.php                     โ† generated by make-base
โ”‚   โ”œโ”€โ”€ CustomService.php
โ”‚   โ”œโ”€โ”€ UserService.php
โ”‚   โ””โ”€โ”€ PostService.php
โ””โ”€โ”€ Models/
    โ”œโ”€โ”€ User.php
    โ””โ”€โ”€ Post.php

๐Ÿ“ฌ Contact

๐Ÿ“ License