bouda/laravel-make-pattern

Generate a full CRUD scaffold (Model, Repository, Service, Controller, Requests, Resource, Policy, Test) from a single Artisan command.

Maintainers

Package info

github.com/Bouda-Bissari/laravel-make-pattern

pkg:composer/bouda/laravel-make-pattern

Transparency log

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 2

Open Issues: 0

v0.1.0 2026-08-03 10:56 UTC

This package is auto-updated.

Last update: 2026-08-05 12:07:11 UTC


README

Latest Version on Packagist Tests Total Downloads License

Generate a full CRUD scaffold — Model, Repository (+ interface), Service, Controller, Form Requests, API Resource, Policy, and a Feature test — from a single Artisan command.

php artisan make:pattern Post

turns into nine consistent, ready-to-edit files, generated from stubs you fully control.

Table of contents

Why

Writing the same repository/service/controller boilerplate for every resource gets old fast, and copy-pasting an existing module invites drift between resources. This package generates all the layers consistently, from stubs you own — no npm-package-style versioning overhead, no opinionated abstraction you can't see or change.

It targets a specific gap: existing Laravel scaffolders are either too minimal (model + migration only) or hard-code an architecture you may not use. Here, every layer is config-driven — disable what you don't need, override any stub, and the generator adapts to your project's conventions instead of the other way around.

Requirements

  • PHP 8.2+
  • Laravel 11.x, 12.x, or 13.x (PHP 8.3+ required for Laravel 13)

Installation

composer require bouda/laravel-make-pattern

The service provider is auto-discovered — nothing to register manually.

Publish the config if your app doesn't follow the default folder conventions:

php artisan vendor:publish --tag=make-pattern-config

Publish the stubs if you want to override the generated code's structure:

php artisan vendor:publish --tag=make-pattern-stubs

Any stub you publish takes priority over the package's built-in one, so you can override a single layer (e.g. just the Controller) without touching the rest.

Usage

php artisan make:pattern Post

Generates:

app/Models/Post.php
app/Repositories/Contracts/PostRepositoryInterface.php
app/Repositories/PostRepository.php
app/Services/PostService.php
app/Http/Controllers/PostController.php
app/Http/Requests/PostStoreRequest.php
app/Http/Requests/PostUpdateRequest.php
app/Http/Resources/PostResource.php
app/Policies/PostPolicy.php
tests/Feature/PostTest.php

For example, the generated repository looks like this:

<?php

namespace App\Repositories;

use App\Models\Post;
use App\Repositories\Contracts\PostRepositoryInterface;

class PostRepository implements PostRepositoryInterface
{
    public function all()
    {
        return Post::all();
    }

    public function find(string $id)
    {
        return Post::findOrFail($id);
    }

    // ...
}

Options

Option Description
--only=model,service Only generate the specified layers
--domain=Blog Generate all layers under app/Domain/Blog/ (DDD style)
--namespace=Acme Override the root namespace (default: App)
--force Overwrite files that already exist

DDD / Domain mode

Use --domain to group all layers under a domain folder:

php artisan make:pattern Post --domain=Blog

Generates:

app/Domain/Blog/Models/Post.php
app/Domain/Blog/Repositories/Contracts/PostRepositoryInterface.php
app/Domain/Blog/Repositories/PostRepository.php
app/Domain/Blog/Services/PostService.php
app/Domain/Blog/Http/Controllers/PostController.php
...

All namespaces follow the same pattern — App\Domain\Blog\Models, App\Domain\Blog\Services, etc.

Custom root namespace

For projects that don't use App\ as their root namespace:

php artisan make:pattern Post --namespace=Acme

Generates files under acme/ with Acme\Models, Acme\Services, etc. Combine with --domain:

php artisan make:pattern Post --domain=Blog --namespace=Acme
# => Acme\Domain\Blog\Models\Post

Configuration

Published to config/make-pattern.php:

Key Description Default
layers.*.enabled Enable/disable a given layer (model, repository, service, controller, requests, resource, policy, test) true
layers.*.namespace / layers.*.path Namespace and output path per layer Laravel default conventions
primary_key.strategy increment, uuid, or ulid ulid
tenancy.enabled / tenancy.driver Adapt generated Model/Repository for a tenant-scoped app (stancl or spatie) false
wrap_repository_calls Wrap generated Repository methods in try/catch with Log::error() before rethrowing (uses repository-with-logging stub instead of repository) false
log_path Deprecated single-run log path, kept for backward compatibility storage/app/make-pattern/last-run.json

This is what makes the generator portable across projects and teams rather than tied to one codebase's conventions.

Generation history & rollback

Every run is recorded in an append-only audit log (storage/app/make-pattern/history.json):

php artisan make:pattern:history
+----+------------+------------------+-------------+
| ID | Entity     | Date             | Files       |
+----+------------+------------------+-------------+
| 3  | Comment    | 2026-08-03 09:15 | 9           |
| 2  | Category   | 2026-08-03 09:10 | 9           |
| 1  | Post       | 2026-08-03 09:02 | 9           |
+----+------------+------------------+-------------+

Undo the last run:

php artisan make:pattern:undo

Or a specific run by id — files modified since generation are left untouched and reported rather than silently deleted:

php artisan make:pattern:undo --id=01ARZ3NDEKTSV4RRFFQ69G5FAV

Logging

Technical/debug output goes to the standard Log facade, separate from the audit history above:

  • info — start and end of a generation (entity, layers, run id, file count)
  • warning — missing stub, or a file skipped because it already exists (use --force)
  • error — an exception during file write (message + stack trace), followed by a clean stop

By default these use the app's default log channel. To keep generator noise out of laravel.log, define a dedicated channel in your app's config/logging.php:

'channels' => [
    'make-pattern' => [
        'driver' => 'single',
        'path' => storage_path('logs/make-pattern.log'),
        'level' => 'info',
    ],
],

The package uses make-pattern automatically when that channel is defined.

Testing

composer test

Tests run against Orchestra Testbench, so no full Laravel app is needed.

Changelog

See CHANGELOG.md for a history of changes.

Contributing

Issues and pull requests are welcome. Please run composer test before submitting a PR.

Security

If you discover a security issue, please open a GitHub issue rather than a public PR with exploit details.

Credits

License

The MIT License (MIT). See LICENSE for more information.