Installation Add the package to your Laravel project via Composer:
composer require dayploy/dart-dto-bundle
Publish the bundle configuration (if applicable):
php artisan vendor:publish --provider="Dayploy\DartDtoBundle\DartDtoServiceProvider"
First Use Case: Basic DTO Definition
Define a simple Data Transfer Object (DTO) in a dedicated Dto namespace (e.g., App\Dto):
namespace App\Dto;
use Dayploy\DartDtoBundle\Dto\Dto;
class UserDto extends Dto
{
public string $name;
public int $age;
}
Instantiation & Usage Instantiate and populate the DTO:
$userDto = new UserDto();
$userDto->name = 'John Doe';
$userDto->age = 30;
// Convert to array (if needed)
$array = $userDto->toArray();
Key Files to Review
config/dart-dto.php (if published)src/Dto/Dto.php (base class)src/Traits/ (optional traits for validation, casting, etc.)Workflow:
Illuminate\Http\Request).use Dayploy\DartDtoBundle\Dto\Dto;
use Illuminate\Http\Request;
class StoreUserRequestDto extends Dto
{
public string $name;
public string $email;
public function rules(): array
{
return [
'name' => 'required|string|max:255',
'email' => 'required|email',
];
}
}
// In a controller:
$dto = new StoreUserRequestDto();
$dto->fill(request()->all());
$dto->validate(); // Built-in validation
Pattern:
use App\Models\User;
use App\Dto\UserDto;
$user = User::find(1);
$dto = UserDto::fromModel($user); // Hypothetical static method
return response()->json($dto->toArray());
Integration Tip:
class AddressDto extends Dto
{
public string $street;
public string $city;
}
class UserDto extends Dto
{
public string $name;
public AddressDto $address;
}
JsonSerializable or custom toArray() methods to flatten nested structures.Workflow:
FormRequest to work with DTOs:
use Illuminate\Foundation\Http\FormRequest;
use App\Dto\StoreUserRequestDto;
class StoreUserRequest extends FormRequest
{
public function validateDto(): StoreUserRequestDto
{
$dto = new StoreUserRequestDto();
$dto->fill($this->validated());
$dto->validate();
return $dto;
}
}
Pattern:
use Dayploy\DartDtoBundle\Dto\Dto;
use Illuminate\Support\Facades\Bus;
class SendEmailCommandDto extends Dto
{
public string $to;
public string $subject;
public string $body;
}
Bus::dispatch(new SendEmailCommand($dto));
Missing Base Class Methods
Dto class may lack common methods like toArray(), fromArray(), or validate(). Override these explicitly:
public function toArray(): array
{
return (array) $this;
}
No Built-in Validation
spatie/laravel-data, this bundle doesn’t include validation rules by default. Implement manually or extend the base class:
use Illuminate\Support\Facades\Validator;
public function validate(): void
{
$validator = Validator::make((array) $this, $this->rules());
if ($validator->fails()) {
throw new \InvalidArgumentException($validator->errors()->first());
}
}
Circular References in Nested DTOs
UserDto containing PostDto which references UserDto) will cause infinite loops in toArray(). Use JsonSerializable or custom serialization logic:
public function jsonSerialize(): array
{
return [
'name' => $this->name,
'address' => $this->address?->jsonSerialize(), // Safe call
];
}
Type Safety
public function setAge(int $age): void
{
if (!is_int($age)) {
throw new \InvalidArgumentException('Age must be an integer.');
}
$this->age = $age;
}
Enable Strict Typing
Add to composer.json to catch type-related issues early:
"config": {
"preferred-visibility": "private",
"sort-packages": true,
"platform-check": true
}
Log DTO Instantiation
Override __construct() to log DTO creation (useful for debugging):
public function __construct()
{
\Log::debug("DTO {$this::class} instantiated");
}
Use get_object_vars() for Debugging
Quickly inspect DTO properties:
dd(get_object_vars($dto));
Add Custom Traits Extend functionality with traits (e.g., for API resource conversion):
use Dayploy\DartDtoBundle\Dto\Dto;
trait ApiResourceable
{
public function toApiResource(): array
{
return array_filter((array) $this, fn ($value) => $value !== null, ARRAY_FILTER_USE_BOTH);
}
}
class UserDto extends Dto
{
use ApiResourceable;
}
Integrate with Laravel Scout Use DTOs to standardize searchable attributes:
class SearchableDto extends Dto
{
public function toSearchableArray(): array
{
return [
'name' => $this->name,
'tags' => explode(',', $this->tags),
];
}
}
DTO Factory Create a factory class to instantiate DTOs from various sources (e.g., database, API):
class DtoFactory
{
public static function fromModel(User $user): UserDto
{
return (new UserDto())
->setName($user->name)
->setEmail($user->email);
}
}
No Default Config File
The package may not publish a config file by default. Check if config/dart-dto.php exists or create it manually to define global DTO behaviors (e.g., default validation rules).
Namespace Collisions
Ensure your Dto classes are in a unique namespace (e.g., App\Dto) to avoid conflicts with Laravel’s built-in classes or other packages.
How can I help you explore Laravel packages today?