Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Логика внутри DTO (Data Transfer Object)
DTO (Data Transfer Object) — это объект, который используется для передачи данных между подсистемами приложения. Его основная цель — инкапсулировать и структурировать данные для эффективной и безопасной передачи.
Базовая логика DTO
Внутренняя логика DTO обычно сводится к следующим аспектам:
1. Структурирование данных
DTO определяет четкую структуру данных, которую ожидают отправитель и получатель. В PHP это чаще всего реализуется как класс с публичными свойствами или с использованием методов доступа.
<?php
class UserRegistrationDTO
{
public string $email;
public string $password;
public string $firstName;
public string $lastName;
public ?DateTimeImmutable $birthDate = null;
public function __construct(
string $email,
string $password,
string $firstName,
string $lastName,
?DateTimeImmutable $birthDate = null
) {
$this->email = $email;
$this->password = $password;
$this->firstName = $firstName;
$this->lastName = $lastName;
$this->birthDate = $birthDate;
}
}
2. Валидация данных (опционально)
Хотя основная валидация обычно происходит на уровне контроллеров или сервисов, DTO может содержать базовую логику проверки данных.
<?php
class OrderCreateDTO
{
public int $userId;
public array $items;
public string $deliveryAddress;
public function __construct(array $data)
{
$this->userId = $data['user_id'] ?? 0;
$this->items = $data['items'] ?? [];
$this->deliveryAddress = $data['delivery_address'] ?? '';
$this->validate();
}
private function validate(): void
{
if ($this->userId <= 0) {
throw new InvalidArgumentException('Invalid user ID');
}
if (empty($this->items)) {
throw new InvalidArgumentException('Order items cannot be empty');
}
}
}
3. Преобразование данных
DTO часто содержит методы для преобразования данных между форматами (массив ↔ объект, объект ↔ JSON).
<?php
class ProductDTO
{
public int $id;
public string $name;
public float $price;
public static function fromArray(array $data): self
{
return new self(
$data['id'],
$data['name'],
$data['price']
);
}
public function toArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'price' => $this->price
];
}
public function toJson(): string
{
return json_encode($this->toArray(), JSON_THROW_ON_ERROR);
}
}
4. Иммутабельность (рекомендуется)
Современные практики рекомендуют делать DTO неизменяемыми (immutable), что предотвращает случайное изменение данных после создания объекта.
<?php
class ImmutableUserDTO
{
public function __construct(
private readonly int $id,
private readonly string $email,
private readonly string $name
) {}
// Только геттеры, сеттеров нет
public function getId(): int
{
return $this->id;
}
public function getEmail(): string
{
return $this->email;
}
public function getName(): string
{
return $this->name;
}
}
5. Нормализация данных
DTO может выполнять предварительную обработку данных: приведение типов, форматирование значений, вычисление производных полей.
<?php
class FinancialReportDTO
{
public float $totalAmount;
public string $formattedAmount;
public string $reportDate;
public function __construct(float $amount, DateTimeInterface $date)
{
$this->totalAmount = round($amount, 2);
$this->formattedAmount = number_format($amount, 2, '.', ' ');
$this->reportDate = $date->format('Y-m-d H:i:s');
}
}
Что НЕ должно быть в DTO
Важно понимать, что DTO — это пассивный объект, который НЕ должен содержать:
- Бизнес-логику приложения
- Сложные вычисления, не связанные с подготовкой данных
- Доступ к базе данных или другим хранилищам
- Зависимости от фреймворка (по возможности)
- Состояние приложения или сессии
Практические преимущества использования DTO
- Типизация данных — строгое определение структуры передаваемых данных
- Декуплинк — уменьшение связности между слоями приложения
- Безопасность — контроль над тем, какие данные передаются между слоями
- Документирование — DTO служит документацией к API или сервису
- Масштабируемость — упрощение рефакторинга и добавления новых полей
Пример комплексного использования
<?php
class ApiResponseDTO
{
public bool $success;
public mixed $data;
public ?string $error = null;
public int $statusCode;
public array $metadata = [];
public function __construct(
bool $success,
mixed $data,
?string $error = null,
int $statusCode = 200,
array $metadata = []
) {
$this->success = $success;
$this->data = $data;
$this->error = $error;
$this->statusCode = $statusCode;
$this->metadata = $metadata;
}
public function toApiFormat(): array
{
return [
'success' => $this->success,
'data' => $this->data,
'error' => $this->error,
'code' => $this->statusCode,
'meta' => $this->metadata,
'timestamp' => time()
];
}
}
// Использование
$response = new ApiResponseDTO(
success: true,
data: ['user_id' => 123, 'email' => 'test@example.com'],
statusCode: 200
);
echo json_encode($response->toApiFormat());
Итог: Логика внутри DTO должна быть минимальной и сосредоточена исключительно на структурировании, валидации и преобразовании данных. DTO служит контрактом между различными частями системы, обеспечивая четкое понимание формата передаваемых данных и повышая надежность всего приложения.