Types & collections
Supported property types
Section titled “Supported property types”| PHP type | OpenAPI output |
|---|---|
string | { "type": "string" } |
int | { "type": "integer" } |
float | { "type": "number" } |
bool | { "type": "boolean" } |
array, Collection | { "type": "array", "items": { ... } } |
| Nested Data class | { "$ref": "#/components/schemas/SomeData" } |
SomeData[] / Collection<int, SomeData> via @var (v4) | typed array of $ref |
DataCollection with #[DataCollectionOf] (v3) | typed array of $ref |
BackedEnum | { "type": "string", "enum": [...] } |
Carbon, DateTime, etc. | { "type": "string", "format": "date-time" } |
string|Optional (Laravel Data) | underlying type, excluded from required |
Nullable (?string) | tracked as not required |
| Default values | included as "default" |
Optional vs nullable
Section titled “Optional vs nullable”Spatie Laravel Data’s Optional marks fields that can be omitted entirely (the “sometimes” validation rule). The generator strips Optional from union types and excludes the property from required.
Nullable (?string) means the field can be present with a null value. Optional means the field can be absent. Both are excluded from required, but they represent different semantics.
use Spatie\LaravelData\Optional;
class UpdateUserRequest extends Data{ public function __construct( public string $id, // required public string|Optional $name, // optional public int|Optional $age, ) {}}Collections
Section titled “Collections”Type collections with @var docblock annotations on plain array or Collection properties:
class OrderData extends Data{ public function __construct( public string $order_number, /** @var OrderItemData[] */ public array $items, ) {}}/** @var Collection<int, OrderItemData> */public Collection $items,Both produce a typed array of $refs. Combine @var with #[GroupedCollection] for dictionary-of-arrays output. Non-Data types like string[] in docblocks are ignored and fall through to plain array handling.
The v3 pattern using DataCollection with #[DataCollectionOf] is still fully supported:
use Spatie\LaravelData\DataCollection;use Spatie\LaravelData\Attributes\DataCollectionOf;
class OrderData extends Data{ public function __construct( #[DataCollectionOf(OrderItemData::class)] public DataCollection $items, ) {}}If you’re migrating from v3 to v4, you can update DTOs incrementally — existing DataCollection properties continue to work alongside new @var docblock properties.
Auto-generated response schemas
Section titled “Auto-generated response schemas”Any DTO whose class name ends with Resource automatically gets three additional wrapper schemas:
| Class | Generated schemas |
|---|---|
ProjectResource | Project, ProjectResponse, ProjectPaginatedResponse, ProjectListResponse |
ProjectResponse:{ status: bool, data: Project }ProjectListResponse:{ status: bool, data: [Project] }ProjectPaginatedResponse:{ status, page, records_per_page, page_count, total_records, data: [Project] }
Pagination wrapper fields are configured via dto.pagination_fields.