← Назад к вопросам

Какая логика внутри DTO?

2.0 Middle🔥 182 комментариев
#Архитектура и паттерны

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Логика внутри 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

  1. Типизация данных — строгое определение структуры передаваемых данных
  2. Декуплинк — уменьшение связности между слоями приложения
  3. Безопасность — контроль над тем, какие данные передаются между слоями
  4. Документирование — DTO служит документацией к API или сервису
  5. Масштабируемость — упрощение рефакторинга и добавления новых полей

Пример комплексного использования

<?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 служит контрактом между различными частями системы, обеспечивая четкое понимание формата передаваемых данных и повышая надежность всего приложения.

Какая логика внутри DTO? | PrepBro