nandan108/dto-toolkit

A modern, framework-agnostic PHP 8.1+ DTO system with attribute-driven data normalization and mapping to entities or arrays.

Maintainers

Package info

github.com/Nandan108/dto-toolkit

pkg:composer/nandan108/dto-toolkit

Statistics

Installs: 33

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 0

v1.4.4 2026-02-22 21:28 UTC

README

CI Coverage Style Packagist

βœ… Requires PHP 8.1–8.5

DTO Toolkit Core is a lightweight, framework-agnostic library for processing Data Transfer Objects (DTOs) in PHP. It provides a unified model for normalization, validation, transformation, and export β€” with first-class support for nested structures and context-aware execution.

The API is fully declarative and attribute-driven: casters, validators, and control-flow modifiers compose into explicit processing pipelines that are JIT-compiled into efficient runtime chains, without coupling to any specific framework.

DTO Toolkit treats data transformation as a lifecycle, not a side effect.

✨ Features

  • 🧱 Conceptually lightweight, framework-agnostic core
  • 🏷️ Attribute-based processing pipelines with explicit control flow
  • 🎯 Optional validation and normalization layers
  • πŸ”„ Easily transform between DTOs and entities/models
  • 🧬 First-class support for nested DTO processing (inbound and outbound), with consistent context propagation
  • 🧩 Designed to work with pluggable framework adapters (Laravel, Symfony, etc.)

πŸ“¦ Installation

composer require nandan108/dto-toolkit

πŸš€ Quick Start

use Nandan108\DtoToolkit\Core\{FullDto, CastTo};

// FullDto includes all standard traits (CreatesFromArrayOrEntity, ProcessesFromAttributes, ExportsOutbound)
class MyDto extends FullDto {
    #[CastTo\Trimmed()]
    public ?string $name = null;
}

final class MyEntity
{
    public ?string $name = null;
}

// Build DTO from array
$dto = MyDto::newFromArray(['name' => '  Alice  ']);

// Transform into an entity (optionally recursive)
$entity = $dto->exportToEntity(MyEntity::class, recursive: true);

Use a framework adapter (e.g. Symfony or Laravel) to unlock request/response integration and validation support.

πŸ“¦ Core Namespace

If you're not using a framework, start with:

  • Nandan108\DtoToolkit\Core\FullDto
  • Nandan108\DtoToolkit\Core\CastTo
  • Nandan108\DtoToolkit\Core\Assert

These provide a convenient, framework-free entry point with all standard functionality included.

πŸ“š Documentation

πŸƒ Runtime & Concurrency

  • Multi-threaded runtimes (pthreads / parallel) are not supported by the core and are not planned to be.
  • Execution context storage is abstracted behind ContextStorageInterface, allowing adapters to provide execution-local storage (e.g. for fibers/coroutines/tasks).
  • Fiber/event-loop runtimes (Swoole, RoadRunner, ReactPHP, etc.) are not officially supported yet.
  • Adapter hooks exist, but full concurrent-runtime support still requires synchronization guarantees around cache warm-up paths, which are not implemented yet.

πŸ”’ Immutability & Value Objects

DTO Toolkit is not an immutable DTO library.

DTOs in DTOT are mutable by design and act as transformation builders: they ingest raw input, apply validation and normalization, and produce clean, structured output. This mutability is what enables DTOT’s dynamic processing model (casting chains, modifiers, context-aware behavior, recursive imports/exports).

That said, DTOT plays very well with immutable objects.

While DTOs themselves are mutable, DTOT is designed to export into immutable value objects or entities via constructor-based instantiation. This allows you to use DTOT as a builder for immutable domain models (value objects), without compromising immutability where it matters.

πŸ‘‰ If you’re looking for immutability at the DTO layer itself, DTOT may not be the right fit.
πŸ‘‰ If you want powerful, declarative transformation pipelines to produce immutable domain objects, DTOT is a strong match.

🧩 Adapter Packages

Adapters will provide support for:

  • Framework-compatible error handling and translations, for both validators and casters
  • fromRequest() for DTO hydration from HTTP requests
  • exportToEntity() or toModel() adapter-specific hydration
  • toResponse() generation
  • DI for class-based casters resolution
  • Graceful handling of validation and casting exceptions in HTTP contexts, with standardized API error responses

πŸ§ͺ Testing & Quality

  • 100% test coverage using PHPUnit
  • Psalm level 1 (maximum strictness)
  • Code style enforced with PHP-CS-Fixer:
    • Based on the @Symfony rule set
    • Aligned => for better readability
    • Disallows implicit loose comparisons (==, !=) except in explicit operator-semantics helpers
  • Commit message style: conventional, with details if any

CI Checks

GitHub Actions (.github/workflows/ci.yml) runs:

  • phpunit on PHP 8.1 to 8.5
  • php-cs-fixer --dry-run (on one matrix leg)
  • psalm (on one matrix leg)
  • composer api-audit-strict (on one matrix leg)

Run Locally Before Push

composer test
composer psalm
composer cs-fix
composer api-audit-strict

Optional: install repository Git hooks (pre-commit + pre-push):

./scripts/setup-hooks.sh

Installed pre-commit runs staged-file PHP-CS-Fixer checks and then optional local extension hook .git/hooks/pre-commit.local if present. Installed pre-push runs composer api-audit-strict, PHPUnit, Psalm, and then optional local extension hook .git/hooks/pre-push.local if present.

🀝 Contributing

Bug reports, ideas, and contributions welcome! This project aims to stay lean, clean, and focused. If you're building an adapter or extending the system, feel free to open a discussion or issue.

🧭 Design Philosophy

This toolkit is built on a simple idea: do the most work with the least number of moving parts.

It favors:

  • Declarative code over procedural boilerplate
  • Clever, expressive syntax without falling into obfuscation
  • Minimalism with power β€” clean by default, extensible when needed
  • Framework-agnostic design with optional adapters that integrate smoothly when needed
  • Zero magic in the core β€” everything is traceable, explicit, and predictable
  • Opt-in magic in adapters β€” for just the right touch of convenience when working with frameworks
  • Separation of concerns and composability β€” inspired by the Unix philosophy of doing one thing well
  • Performance-conscious by design β€” DTOs should feel lightweight and fast to use, even in large batch transformations.

Verbose code is a tax on your time. This toolkit aims to keep things sharp, concise, and purposeful β€” so you can focus on what matters.

MIT License Β© nandan108