Search by

sazl / laravel-repokit

AffanAbd97

Repository Pattern implementation for Laravel

Package info

github.com/AffanAbd97/laravel-repokit

pkg:composer/sazl/laravel-repokit

Statistics

Installs: 16

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v2.1.1 2026-09-10 04:34 UTC

This package is auto-updated.

Last update: 2026-11-03 04:24:29 UTC


README

PHP Laravel License

Generate Laravel repositories, services, and their interfaces with Artisan. Create both layers in one command, choose Query Builder or Eloquent, and customize the generated code through published stubs.

Controller → Service → Repository → Database

Requirements

PHP ^8.1 and Laravel 10.x, 11.x, or 12.x, with a PHP version supported by your Laravel release.

Installation

composer require sazl/laravel-repokit

Laravel discovers Sazl\LaravelRepokit\Providers\RepokitProvider automatically through Composer.

Usage

Use a base name such as User or user_profile. Names are converted to StudlyCase, then given the appropriate repository, service, or interface suffix.

Generate a complete module

php artisan make:module User

Creates a repository, a service that injects its repository interface, and both interfaces. It also records the bindings in config/repository.php and config/service.php.

The repository uses Query Builder by default. To inject an Eloquent model instead:

php artisan make:module User --model=User

The model resolves to App\Models\User. The command generates the repository and service files; create the model separately. See Configuration and bindings for repository container registration.

Generate a repository

php artisan make:repository User

Creates app/Repositories/Contracts/UserRepositoryInterface.php and app/Repositories/Databases/UserRepository.php.

The default implementation uses the DB facade, the mysql connection, and a plural snake_case table name such as users. Adjust the generated connection and table properties for your application.

To use an Eloquent model:

php artisan make:repository User --model=User

--model also accepts a full namespace:

php artisan make:repository User --model='App\Custom\User'

The short option is -M. The same model options work with make:module.

Generate a service

php artisan make:service User

Creates app/Services/Contracts/UserServiceInterface.php and app/Services/UserService.php. By default, the service injects App\Repositories\Contracts\UserRepositoryInterface.

To inject a different repository interface:

php artisan make:service Order --repository=User

The short option is -R. Pass the repository's base name. This command creates only the service and its interface, so generate the repository separately or use make:module to create both layers.

Generate an empty service

php artisan make:service User --empty

The short option is -e. The bundled empty template removes the pre-built methods from the interface and service, but keeps the constructor and repository injection. You can combine --empty with --repository.

Replace existing files

All three generators stop when they encounter an existing target file unless --force is supplied:

php artisan make:module User --model=User --force
php artisan make:repository User --force
php artisan make:service User --empty --force

These are separate examples. Rerun with the options you want in the replacement files. --force overwrites every existing file generated by that command, discarding manual changes. For a module, this includes all four files. Existing config bindings remain unchanged, even with --force.

Without --force, an existing file produces this message:

File already exists: /project/app/Repositories/Contracts/UserRepositoryInterface.php
Choose a different name, or rerun with --force to overwrite existing files. Manual changes will be lost.

Files are written in order. If a later file conflicts, files written earlier in that run remain on disk.

Generated file structure

For make:module User:

app/
├── Repositories/
│   ├── Contracts/
│   │   └── UserRepositoryInterface.php
│   └── Databases/
│       └── UserRepository.php
└── Services/
    ├── Contracts/
    │   └── UserServiceInterface.php
    └── UserService.php
config/
├── repository.php
└── service.php

The bundled templates provide these methods:

Repository Service Behavior
all() getAll() Fetch all records.
find($id) getById($id) Find a record by ID.
create(array $data) create(array $data) Insert a record.
update($id, array $data) update($id, array $data) Update a record by ID.
delete($id) delete($id) Delete a record by ID.

Service methods delegate to the injected repository. Query Builder create() returns an inserted ID, while Eloquent create() returns a model. The Eloquent template returns false when updating or deleting a missing record.

Configuration and bindings

Generators publish the relevant config file automatically if it is missing. You can also publish the files directly:

php artisan vendor:publish --tag=repository-config
php artisan vendor:publish --tag=service-config

Repository mappings are written to config/repository.php:

<?php

return [
    'bindings' => [
        \App\Repositories\Contracts\UserRepositoryInterface::class => \App\Repositories\Databases\UserRepository::class,
    ],
];

Service mappings are written to config/service.php:

<?php

return [
    'bindings' => [
        \App\Services\Contracts\UserServiceInterface::class => \App\Services\UserService::class,
    ],
];

An existing mapping for an interface is kept as-is. Adding a new mapping rewrites the config file as a bindings array, so keep unrelated settings and comments elsewhere.

The current package provider loads service.bindings into Laravel's container when the interface and implementation exist. It does not currently load repository.bindings. To resolve a generated service's repository dependency, add this binding to your application's AppServiceProvider::register():

$this->app->bind(
    \App\Repositories\Contracts\UserRepositoryInterface::class,
    \App\Repositories\Databases\UserRepository::class,
);

Repeat the binding for each generated repository. The generators write config mappings; they do not edit AppServiceProvider.

Console output

For php artisan make:module User --model=User, with config files already published and no existing generated files:

Generating module [User].
Repository model: App\Models\User
Created: /project/app/Repositories/Contracts/UserRepositoryInterface.php
Created: /project/app/Repositories/Databases/UserRepository.php
Created: /project/app/Services/Contracts/UserServiceInterface.php
Created: /project/app/Services/UserService.php
Registered binding in config/repository.php: App\Repositories\Contracts\UserRepositoryInterface => App\Repositories\Databases\UserRepository.
Registered binding in config/service.php: App\Services\Contracts\UserServiceInterface => App\Services\UserService.

Paths are absolute and depend on your project location. Each successful write reports Created: or Overwritten:. A new file still reports Created: when --force is supplied.

Repository and module commands show the selected model or Repository type: Query Builder. Service commands show the repository interface and identify an empty template when selected.

Existing bindings report already exists and left unchanged. Missing or unwritable config files produce an error message after file generation.

Customize generated code

Publish the stubs into your application:

php artisan vendor:publish --tag=repokit-stubs

Edit the files under resources/stubs/vendor/repokit/:

Stub Used for
repositories/contract.stub Repository interfaces.
repositories/implementation.stub Query Builder repositories.
repositories/implementation.model.stub Repositories generated with --model.
services/contract.stub Standard service interfaces.
services/implementation.stub Standard services, including those generated by make:module.
services/contract.empty.stub Service interfaces generated with --empty.
services/implementation.empty.stub Services generated with --empty.

Keep the existing {{ ... }} placeholders where you want the generators to insert names and model details. Published stubs take precedence over bundled stubs. If a published file is missing, the generator falls back to the corresponding bundled file.

Stub edits affect future generation. Regenerating existing files requires --force and replaces their contents with the newly rendered stubs.

Command reference

Command Options Result
make:module {name} --model / -M, --force Repository, service, both interfaces, and both config mappings.
make:repository {name} --model / -M, --force Repository, interface, and repository config mapping.
make:service {name} --repository / -R, --empty / -e, --force Service, interface, and service config mapping.

Local development

Clone the package and install its dependencies:

git clone https://github.com/sazl/laravel-repokit.git
cd laravel-repokit
composer install

The test suite uses PHPUnit and Orchestra Testbench. Run it from the package directory:

php vendor/bin/phpunit

To use your local checkout in a Laravel application, add a path repository to that application's composer.json:

{
    "repositories": [
        {
            "type": "path",
            "url": "../laravel-repokit",
            "options": {
                "symlink": true
            }
        }
    ]
}

Adjust url relative to the Laravel application's directory. Then run this command from that application:

composer require sazl/laravel-repokit:@dev

The path repository requests a symlink so local package edits are reflected in the application. Laravel discovers the package provider through its Composer metadata.

License

MIT