Vortos
Make

Customizing Stubs

Override any framework stub with your own project template — your version always wins.

Customizing Stubs

Every vortos:make:* command renders a stub template before writing the file. Stubs live inside each module's Resources/stubs/ directory. You can override any stub by placing a file with the same name in your project's stubs/ directory — your version always takes priority.

How Resolution Works

When a command needs a stub, StubScanner checks two locations:

1. {project-root}/stubs/{stub-name}.stub       ← your project override (wins)
2. {module}/Resources/stubs/{stub-name}.stub   ← framework default (fallback)

If your override exists, the framework stub is never read. If your override does not exist, the framework default is used. This means you can override individual stubs without forking the package.

Creating an Override

  1. Find the stub name for the command you want to customise. The name is the hyphenated identifier used internally — for example, entity, command, event-handler.

  2. Create stubs/ in your project root if it doesn't exist:

mkdir -p stubs
  1. Copy the framework stub as a starting point:
# Stubs live in the installed package, e.g.:
cp vendor/vortos/vortos-domain/Resources/stubs/entity.stub stubs/entity.stub
  1. Edit stubs/entity.stub to match your project conventions.

The next time you run vortos:make:entity, your stub is used.

Stub Variable Syntax

All stubs use double-curly-brace placeholders: {{VariableName}}. Each command passes a fixed set of variables. The table below lists every placeholder and which commands provide it.

PlaceholderProvided byDescription
{{Namespace}}AllPHP namespace for the generated class
{{ClassName}}AllClass name
{{HttpStatus}}domain-errorHTTP status code (e.g. 404, 409)
{{ErrorCode}}domain-errorSCREAMING_SNAKE_CASE error code (e.g. USER_NOT_FOUND)
{{TableName}}entity, write-repositorySQL table name (snake_case plural)
{{CollectionName}}read-repositoryMongoDB collection name
{{ConsumerName}}consumer, projection-handler, messaging-configKafka consumer name
{{HandlerId}}consumer, projection-handlerUnique handler ID (dot.case)
{{EventImport}}consumer, projection-handlerFull use statement for the event class
{{EventType}}projection-handlerShort event class name
{{EventClass}}consumerFull FQCN of the event
{{EventShortClass}}consumerShort name of the event
{{TransportName}}messaging-configKafka transport name
{{TopicName}}messaging-configKafka topic name
{{GroupId}}messaging-configKafka consumer group ID
{{Priority}}middlewareMiddleware execution priority
{{HookAttribute}}hookAttribute class name (e.g., BeforeDispatch)
{{Resource}}authorization-policyResource slug
{{Bucket}}quota-resolverQuota bucket name
{{AttributeKey}}quota-resolverIdentity attribute key
{{RoutePrefix}}controllerHTTP route path
{{RouteName}}controllerHTTP route name
{{RouteMethod}}controllerHTTP method
{{AggregateNamespace}}write-repositoryNamespace of the aggregate class
{{AggregateClass}}write-repositoryAggregate class name
{{Idempotent}}consumertrue or false

Example: Adding a Constructor Body to Commands

The default command.stub generates an empty constructor. If every command in your project needs a specific set of properties, override it:

stubs/command.stub
<?php

declare(strict_types=1);

namespace {{Namespace}}\Application\Command\{{ClassName}};

use Vortos\Domain\Command\AbstractCommand;

final class {{ClassName}} extends AbstractCommand
{
    public function __construct(
        public readonly string $actorId,
        // add command properties here
    ) {}
}

Every vortos:make:command invocation will now include $actorId in the generated command.

Example: Adding Strict Type Annotations

Override value-object.stub to include PHPStan/Psalm annotations:

stubs/value-object.stub
<?php

declare(strict_types=1);

namespace {{Namespace}}\Domain\ValueObject;

/** @psalm-immutable */
final readonly class {{ClassName}}
{
    private function __construct(private string $value) {}

    /** @pure */
    public static function fromString(string $value): self
    {
        return new self($value);
    }

    public function equals(self $other): bool
    {
        return $this->value === $other->value;
    }

    public function __toString(): string
    {
        return $this->value;
    }
}

Listing Available Framework Stubs

All stubs are discoverable by looking in the installed packages:

find vendor/vortos -name "*.stub" -path "*/Resources/stubs/*" | sort

Stubs Are Per-Module

Stubs are owned by the module they belong to — entity.stub lives in vortos-domain, command.stub lives in vortos-cqrs, event-handler.stub in vortos-messaging. When you copy a stub to override it, check which package owns it so you copy the right file.

Sharing Stubs Across Teams

Commit your stubs/ directory to source control. Everyone on the team picks up your overrides automatically — the resolution logic checks the project root stubs/ directory at runtime, so no configuration is needed beyond the file being present.

On this page