solido/dto-management
Manage, discover, and enhance DTOs in PHP apps with Solido DTO Management. Provides tools to register and locate DTO classes and apply enhancements consistently across your codebase. Documentation and contribution guides available.
Installation
composer require solido/dto-management
Publish the config (if needed):
php artisan vendor:publish --provider="Solido\DTOManagement\DTOManagementServiceProvider"
Define a DTO
Create a class extending Solido\DTOManagement\DTO:
namespace App\DTO;
use Solido\DTOManagement\DTO;
class UserDTO extends DTO
{
public string $name;
public int $age;
}
Register DTOs
In config/dto-management.php, add your DTOs under the dto key:
'dto' => [
'App\DTO\UserDTO' => [
'version' => '1.0',
'description' => 'User data transfer object',
],
],
First Use Case: Fetching a DTO
use Solido\DTOManagement\Facades\DTOManager;
$userDTO = DTOManager::getDTO('App\DTO\UserDTO');
$userDTO->name = 'John Doe';
$userDTO->age = 30;
DTO Versioning
config/dto-management.php:
'App\DTO\UserDTO' => [
'versions' => [
'1.0' => ['fields' => ['name', 'age']],
'2.0' => ['fields' => ['name', 'age', 'email']],
],
],
$userDTO = DTOManager::getDTO('App\DTO\UserDTO', '2.0');
DTO Enhancement Extend DTOs dynamically with traits or methods:
namespace App\DTO;
use Solido\DTOManagement\DTO;
use Solido\DTOManagement\Enhancer\DTOEnhancer;
class UserDTO extends DTO
{
public string $name;
public function fullName(): string
{
return "User: {$this->name}";
}
}
// Register enhancer in config:
'enhancers' => [
'App\DTO\UserDTO' => [
'App\DTO\Enhancers\UserEnhancer',
],
],
DTO Validation Use built-in validation rules:
class UserDTO extends DTO
{
public string $name;
public int $age;
protected function rules(): array
{
return [
'name' => 'required|string|max:255',
'age' => 'required|integer|min:18',
];
}
}
DTO Serialization Convert DTOs to arrays or JSON:
$userDTO = DTOManager::getDTO('App\DTO\UserDTO');
$userDTO->name = 'Jane Doe';
$userDTO->age = 25;
$array = $userDTO->toArray();
$json = $userDTO->toJson();
DTO Factory Create DTOs from arrays or other DTOs:
$data = ['name' => 'Alice', 'age' => 30];
$userDTO = DTOManager::createDTO('App\DTO\UserDTO', $data);
Laravel Request Binding Bind DTOs to incoming requests:
use Illuminate\Http\Request;
use Solido\DTOManagement\Facades\DTOManager;
public function store(Request $request)
{
$dto = DTOManager::bindDTO('App\DTO\UserDTO', $request->all());
// Process $dto
}
API Responses Return DTOs as API responses:
return response()->json(DTOManager::getDTO('App\DTO\UserDTO', $data));
Event Dispatching Dispatch events when DTOs are created or updated:
DTOManager::getDTO('App\DTO\UserDTO', $data)->dispatchEvents();
Testing Mock DTOs in tests:
$mockDTO = Mockery::mock('overload:' . App\DTO\UserDTO::class);
$mockDTO->shouldReceive('name')->andReturn('Test User');
DTO Registration
config/dto-management.php will throw DTONotFoundException.dto key.Version Mismatches
UndefinedPropertyException.DTOManager::supportsVersion() to check compatibility:
if (DTOManager::supportsVersion('App\DTO\UserDTO', '2.0', 'email')) {
$dto->email = 'test@example.com';
}
Circular References
UserDTO has AddressDTO, which has UserDTO) can cause infinite loops during serialization.DTOManager::setCircularReferenceHandler():
DTOManager::setCircularReferenceHandler(function ($dto) {
return $dto->id; // Return a simple identifier
});
Enhancer Conflicts
config/dto-management.php or use namespaced enhancer classes.Validation Overrides
rules() methods in DTOs are merged with config-based rules, which can lead to unexpected behavior.Enable Debug Mode
Set 'debug' => true in config/dto-management.php to log DTO operations.
DTO Dumping
Use DTOManager::dumpDTO() to inspect DTO structure:
DTOManager::dumpDTO('App\DTO\UserDTO', '2.0');
Event Listening Listen for DTO events to debug lifecycle:
DTOManager::listen('dto.created', function ($dto) {
\Log::debug('DTO created:', $dto->toArray());
});
Custom DTO Resolvers
Override how DTOs are resolved by binding to dto.resolved event:
DTOManager::listen('dto.resolved', function ($dto, $version) {
if ($version === '2.0') {
$dto->email = 'default@example.com';
}
});
Dynamic DTO Generation
Use DTOManager::generateDTO() to create DTOs from runtime definitions:
$dynamicDTO = DTOManager::generateDTO(
'DynamicUserDTO',
['name' => 'string', 'age' => 'integer'],
'1.0'
);
DTO Middleware Apply middleware to DTO operations:
DTOManager::extend('App\DTO\UserDTO', function ($dto) {
$dto->setMiddleware(function ($dto) {
// Pre-process DTO
});
});
Custom Serializers Replace default serialization with a custom strategy:
DTOManager::setSerializer(function ($dto) {
return json_encode($dto->toArray(), JSON_PRETTY_PRINT);
});
Caching DTO definitions are cached by default. Clear cache after changes:
php artisan cache:clear
Autoloading
Ensure DTO classes are autoloaded. Add them to composer.json:
"autoload": {
"psr-4": {
"App\\DTO\\": "app/DTO/"
}
}
Namespace Conflicts
Avoid naming DTOs with reserved words (e.g., DTO, Manager). Use explicit namespaces.
Environment-Specific Config Override DTO versions per environment:
'dto' => env('DTO_ENV', [
'App\DTO\UserDTO' => ['version' => '1.0'],
]),
How can I help you explore Laravel packages today?