touhidurabir/laravel-stub-generator
A Laravel package for generating and customizing stub files so Artisan make commands scaffold controllers, models, migrations, and other classes using your own templates. Publish and manage stubs to standardize boilerplate across projects.
Install the package
composer require touhidurabir/laravel-stub-generator
The service provider should be auto-discovered on Laravel 5.5+. If not, register Touhidurabir\StubGenerator\StubGeneratorServiceProvider manually in config/app.php.
Publish config and stubs
php artisan vendor:publish --provider="Touhidurabir\StubGenerator\StubGeneratorServiceProvider"
If that publishes everything, re-run with --tag= to separate the config from the stub files. Confirm the available tags with php artisan vendor:publish --list (or by reading the provider's publishes() array).
Look here first
config/stub-generator.php — stub locations, target paths, namespace mappings, and any placeholder configuration.stubs/ directory — one stub per artifact type (service.stub, repository.stub, trait.stub, etc.).php artisan list | grep -i stub — the actual command signature is the fastest way to learn the package's public API.First use case: scaffold an app service
Create stubs/service.stub with placeholders such as {{ namespace }}, {{ class }}, and {{ extends }}, point the config at it, then generate:
php artisan stub:generate service UserService
The generated file should land in app/Services/UserService.php with the correct namespace. Once that round-trip works, you have validated path resolution, placeholder replacement, and namespace derivation in one shot — the three things that typically break.
action, dto, policy) should mean adding a stub and a config entry, not writing code.make:service, make:action, make:repository) that validate the name, call the generator, and optionally register the class in a service provider. This keeps the package as an implementation detail you can swap out.handle():
$generator->from('stubs/service.stub')
->to(app_path('Services'))
->with(['namespace' => 'App\\Services', 'class' => $name])
->generate();
Exact method names vary by version — read the source of the facade/class once and pin your wrapper around it so upgrades are contained.stubs/. On upgrade, diff the package's default stubs against your overrides to catch renamed placeholders.make:* commands. A common pattern is to have your custom command call Artisan::call('make:model', ...) first, then run the stub generator for the service/repository layer, giving you a single "feature scaffold" command.$this->artisan('make:service', ['name' => 'Foo']);
$this->assertFileContains('app/Services/FooService.php', 'class FooService');
This catches broken stubs and placeholder regressions without testing third-party internals.File::exists() or expose a --force flag so repeated runs don't silently overwrite hand-edited code.{{ }} and you also run them through Blade or any templating layer, the two will fight. Verify whether the package replaces placeholders itself or compiles the stub; escape or change delimiters if needed.{{class}} vs {{ class }} or {{ ClassName }} will silently leave the literal token in the output. Grep generated files for {{ in a post-generation test.app/Services/X.php declaring namespace App\Service. Derive namespace from the configured PSR-4 root, not from a hardcoded string, and confirm composer.json maps the target directory.php artisan config:clear. In production-style environments with cached config, new stub entries appear to be ignored.base_path()/app_path() over string concatenation.^[A-Z][A-Za-z0-9]*$ or similar) to prevent ../ escaping the target directory.Generator/Stub facade, events fired around generation, and config keys for custom placeholder replacers. These are the cleanest hooks for project-specific behavior.composer.json, keep your own thin wrapper around it, and be prepared to replace it with a ~50-line internal generator if it goes unmaintained — the core feature (read stub, replace tokens, write file) is not large.How can I help you explore Laravel packages today?