cuongnx / laravel-repo-service-generator
Generate repository-service structure for Laravel with interface and binding
Package info
github.com/xuancuong220691/laravel-repo-service-generator
pkg:composer/cuongnx/laravel-repo-service-generator
Requires
- php: >=8.1
- illuminate/support: ^11.0 || ^12.0
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
- Installation
- Generate Base Classes
- Full Structure Generation
- Create Simple Service
- Bindings
- Unbind
- Remove Structures
- Subdirectory Support
- BaseRepository Methods
- BaseService Methods
- Advanced Query Conditions
- Folder Structure
โ๏ธ 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-basebefore 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/toandmin/maxusewhereBetween()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
- Email: xuancuong220691@gmail.com
๐ License
- MIT License ยฉ Cuong Nguyen