Stubs
A stub holds the contents a generated class starts from. Laravel's file types start from Laravel's own stubs. File types mod adds start from mod's stubs, or from an empty class, and your app can replace any of them.
Custom generators creates commands from generator templates. This page covers contents, starters and bases.
Starting From Your Own Stub
A file type with no Laravel generator starts as an empty class. To start from your own stub, add stubs/mod.<type>.stub to your app. For the repository file type from Adding a Layer, which writes a repository for a Document model in the Knowledge domain:
<?php
namespace {{ namespace }};
class {{ class }}
{
//
}php artisan mod:repository Knowledge:Document
# -> src/Infrastructure/Knowledge/Repositories/DocumentRepository.php, from stubs/mod.repository.stubstubs/mod.<type>.stub works for every file type, including those with a Laravel generator, and wins over every other stub. Its placeholders:
| Placeholder | Filled with |
|---|---|
{{ namespace }}, {{ class }} | the class's namespace and short name |
{{ base }}, {{ baseClass }} | the base class's full and short name |
{{ baseImport }} | its use line, or nothing when there is no base |
{{ extends }} | extends <baseClass>, or nothing when there is no base |
Starter Stubs
DTOs, view models, value objects and actions start as plain Laravel-style classes. When a package for them is installed, mod uses it instead:
| Command | When installed | Otherwise |
|---|---|---|
mod:dto | spatie/laravel-data: extends Data | extends a DataTransferObject base with fromArray() and toArray() |
mod:view-model | spatie/laravel-view-models: extends ViewModel | extends a ViewModel base |
mod:action | lorisleiva/laravel-actions: use AsAction; | a plain class with handle() |
mod:value-object | a plain class with a constructor |
The command says which it used:
php artisan mod:dto Knowledge:DocumentData
# -> INFO Using spatie/laravel-data (installed).The modules and ddd layouts have all four commands. In any layout, a file type with the id dto (or data), view-model, value-object (or value) or action starts from the matching starter. Add one to the features layout and it starts as a DTO:
use Tey\Mod\Facades\Mod;
Mod::layout('features')->generates('dto', in: 'Features/{feature}/Data');php artisan mod:dto Knowledge:DocumentData
# -> INFO Created base class App\Support\Data\DataTransferObject [app/Support/Data/DataTransferObject.php].
# -> INFO DTO [app/Features/Knowledge/Data/DocumentData.php] created successfully.A file type with another id uses a starter through stub::
use Tey\Mod\Facades\Mod;
use Tey\Mod\Generation\Starters;
Mod::layout('features')->generates('payload', in: 'Features/{feature}/Payloads', stub: Starters::dto());Starters::dto(), Starters::viewModel(), Starters::valueObject() and Starters::action() are the four starters.
Generated Base Classes
Without spatie/laravel-data, the first mod:dto writes a DataTransferObject base into your app:
php artisan mod:dto Knowledge:DocumentData INFO Created base class App\Support\Data\DataTransferObject [app/Support/Data/DataTransferObject.php].
INFO DTO [app/Modules/Knowledge/Data/DocumentData.php] created successfully.Bases go in app/Support: App\Support\Data\DataTransferObject and App\Support\ViewModels\ViewModel, the same classes for every module. To put them somewhere else, set bases_path. The ddd layout keeps them in src/Domain/Shared, where laravel-ddd puts them:
php artisan mod:dto Knowledge:DocumentData
# -> INFO Created base class Domain\Shared\Data\DataTransferObject [src/Domain/Shared/Data/DataTransferObject.php].A base is written the first time it is needed, and it is yours from then on: mod never overwrites it, not even with --force. To change what it starts as, add stubs/mod.base.data-transfer-object.stub or stubs/mod.base.view-model.stub to your app.
Writing Missing Bases
A module copied from another project refers to bases it doesn't contain. mod:bases writes every base your layout can use that is missing, whether or not a class extends it yet:
php artisan mod:bases INFO Created base class App\Support\Data\DataTransferObject [app/Support/Data/DataTransferObject.php].
INFO Created base class App\Support\ViewModels\ViewModel [app/Support/ViewModels/ViewModel.php].It never overwrites a base. When every base exists, it says so and writes nothing:
INFO Every base class already exists.Using Your Own Base Class
To extend a class of your own instead, set it in config/mod.php, by file type. A configured base wins over an installed package:
'bases' => [
'dto' => App\Support\BaseData::class,
],php artisan mod:dto Knowledge:DocumentData
# -> INFO Using the configured base App\Support\BaseData.view-model, value-object and action take a base the same way.
Using the Base in Your Stub
A stub of your own uses {{ baseImport }} and {{ extends }} for the base mod chose, so one file serves every case:
<?php
namespace {{ namespace }};
{{ baseImport }}
class {{ class }}{{ extends }}
{
public function __construct(
//
) {}
}Stack-aware Scaffold Stubs
A member's stub: 'list' uses a key such as page.list. Register extension-specific variants for each supported frontend stack:
use Tey\Mod\Facades\Mod;
use Tey\Mod\Generation\Stub;
Mod::stubs()->forFileType('page.list.vue', Stub::file(__DIR__.'/../stubs/list.vue.stub'));
Mod::stubs()->forFileType('page.list.tsx', Stub::file(__DIR__.'/../stubs/list.tsx.stub'));
Mod::stubs()->forFileType('page.list.jsx', Stub::file(__DIR__.'/../stubs/list.jsx.stub'));For a planned .tsx page, lookup is the app's stubs/mod.page.list.tsx.stub, then the registered page.list.tsx, then the registered page.list fallback. The app's stub wins. Use the extension-free key only for content that works across stacks. Another stack's key is never used: without a matching variant or fallback the plan names the stub to supply and writes nothing. The same precedence applies to flat recipes, tree members and parts, and to any file type with an extension (for example view.card.blade.php).