Customizing Stubs in Laravel

Published on by

Customizing Stubs in Laravel image

This post will show you how to customize stubs used to generate various classes in your application. While a minor inconvenience, manually adjusting every generated class can be tedious, and Laravel provides a way for developers to publish and version stubs in an application if you want to suit generated classes to your specific taste.

If you want to follow along, you can create a new Laravel project with the Laravel installer, using Sail, or any other way you prefer to create a new application:

laravel new stub-demo --git

You might have noticed that the Laravel installer now supports Git and GitHub integration assuming you have the minimum git version required, you should have a new repository and a first commit.

Versioning our demo project is an excellent way to visualize the stub changes we make along the way and see what kind of files Laravel publishes to the app.

Publishing Stubs

The first step in customizing stubs could be to add stubs you'd like to customize individually to the /stubs folder at the root of a Laravel project, or you can publish all of them with Artisan:

$ php artisan stub:publish
$ git add stubs
$ git status
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
 
new file: stubs/cast.stub
new file: stubs/console.stub
new file: stubs/controller.api.stub
new file: stubs/controller.invokable.stub
new file: stubs/controller.model.api.stub
new file: stubs/controller.model.stub
new file: stubs/controller.nested.api.stub
new file: stubs/controller.nested.stub
new file: stubs/controller.plain.stub
new file: stubs/controller.stub
new file: stubs/factory.stub
new file: stubs/job.queued.stub
new file: stubs/job.stub
new file: stubs/middleware.stub
new file: stubs/migration.create.stub
new file: stubs/migration.stub
new file: stubs/migration.update.stub
new file: stubs/model.pivot.stub
new file: stubs/model.stub
new file: stubs/observer.plain.stub
new file: stubs/observer.stub
new file: stubs/policy.plain.stub
new file: stubs/policy.stub
new file: stubs/request.stub
new file: stubs/resource-collection.stub
new file: stubs/resource.stub
new file: stubs/rule.stub
new file: stubs/seeder.stub
new file: stubs/test.stub
new file: stubs/test.unit.stub

As you can see, we have quite a few stubs published in the app folder! I'll leave it up to you if you want to version all of them, but you could either keep a copy of them or only keep the specific stubs you want to customize.

Custom Controller Stubs

Laravel 8.36 introduced the idea of a --type flag when making a controller, allowing you to write custom stub files for generating a controller:

<?php
// stubs/controller.custom.stub
namespace {{ namespace }};
 
use {{ rootNamespace }}Http\Controllers\Controller;
use Illuminate\Http\Request;
 
/**
* Hello from the custom controller stub
*/
class {{ class }}
{
//
}

After adding the custom stub class, you can generate a controller using this template:

php artisan make:controller --type=custom MyController

Which would generate the following controller file:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
/**
* Hello from the custom controller stub
*/
class MyController
{
//
}

While this flexibility level is neat, I believe most developers can fit within the bounds of the stubs provided by the framework. Using the new --type flag is a manual way of picking which controller template you want to generate:

php artisan make:controller --type=plain PlainController

Which would generate a file based on the stubs/controller.plain.stub file published by Laravel:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
 
class PlainController extends Controller
{
//
}

A Sane Approach

Suppose you wanted to prepend a copyright comment to every file generated in your Laravel application. In that case, you could consider versioning all available stubs, and as you upgrade, run the stub:publish command to get newly added stubs.

For typical use-cases, though, perhaps you might only version the stubs you need to customize. For example, let's say that you don't want any controllers to extend the base Controller class; you could version all the controller.* stubs with your customizations but remove all the other stubs.

What If Stubs Change Upstream?

Let's say you version all the stubs from stub:publish, but you are concerned that as the Laravel framework receives updates to core stub files, your app will be out-of-date. If you version all stubs, you can always force an update to get the latest versions.

Take this for example, let's modify a stub and commit it to Git:

echo "/* test */" >> stubs/test.stub
git commit -am"Testing stub update"

You've updated the test stub and committed the update to Git. Let's say later Laravel publishes some updates to stubs and you want to verify if any have changed:

$ php artisan stub:publish --force
$ git diff
diff --git a/stubs/test.stub b/stubs/test.stub
index 834a53d..84c75cb 100644
--- a/stubs/test.stub
+++ b/stubs/test.stub
@@ -20,4 +20,3 @@ class {{ class }} extends TestCase
$response->assertStatus(200);
}
}
-/* test */

You have an easy way to see how your stubs have diverged from the Laravel codebase over time! Since the stubs are versioned you can simply undo changes the --force flag causes if you need to merge your changes with the latest stub changes.

Paul Redmond photo

Staff writer at Laravel News. Full stack web developer and author.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

Laravel Forge logo

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
LaraJobs logo

LaraJobs

The official Laravel job board

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate logo

Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate

Build your SaaS application in hours. Out-of-the-box multi-tenancy and seamless Stripe integration. Supports subscriptions and one-time purchases, allowing you to focus on building and creating without repetitive setup tasks.

Supercharge Your SaaS Development with FilamentFlow: The Ultimate Laravel Filament Boilerplate
Rector logo

Rector

Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies

Rector
MongoDB logo

MongoDB

Enhance your PHP applications with the powerful integration of MongoDB and Laravel, empowering developers to build applications with ease and efficiency. Support transactional, search, analytics and mobile use cases while using the familiar Eloquent APIs. Discover how MongoDB's flexible, modern database can transform your Laravel applications.

MongoDB

The latest

View all →
Asymmetric Property Visibility in PHP 8.4 image

Asymmetric Property Visibility in PHP 8.4

Read article
Access Laravel Pulse Data as a JSON API image

Access Laravel Pulse Data as a JSON API

Read article
Laravel Forge adds Statamic Integration image

Laravel Forge adds Statamic Integration

Read article
Transform Data into Type-safe DTOs with this PHP Package image

Transform Data into Type-safe DTOs with this PHP Package

Read article
PHPxWorld - The resurgence of PHP meet-ups with Chris Morrell image

PHPxWorld - The resurgence of PHP meet-ups with Chris Morrell

Read article
Herd Executable Support and Pest 3 Mutation Testing in PhpStorm 2024.3 image

Herd Executable Support and Pest 3 Mutation Testing in PhpStorm 2024.3

Read article