В современных веб-приложениях обычно используются разные уровни приложения, такие как уровень базы данных, уровень бизнес-логики и уровень представления. Каждый уровень отвечает за определенную задачу и взаимодействует с другими уровнями через интерфейсы. Однако при передаче данных между этими слоями могут возникнуть трудности с управлением данными и обеспечением их правильной передачи. Вот тут-то и появляются объекты передачи данных (DTO).
DTO — это шаблон проектирования, используемый для передачи данных между уровнями приложения. DTO — это объект, который переносит данные между процессами, например, между веб-приложением и базой данных. Это простой контейнер для данных, в котором нет никакой бизнес-логики, проверки или других операций.
Одним из наиболее распространенных применений DTO является передача данных между уровнями приложения. Например, при извлечении данных из базы данных данные могут быть возвращены в виде массива или набора результатов базы данных. Однако уровень бизнес-логики может потребовать, чтобы данные были в определенном формате или типе. DTO можно использовать для преобразования данных из одного формата в другой и обеспечения их правильной передачи на следующий уровень.
Другое использование DTO — определение структуры объектов ответа, возвращаемых API. При разработке API важно определить структуру объектов ответа, чтобы обеспечить их согласованность и простоту использования клиентскими приложениями. DTO можно использовать для определения структуры объекта ответа и обеспечения того, чтобы он содержал все необходимые данные.
Теперь, когда вы хорошо понимаете, что такое объекты передачи данных (DTO) и почему они полезны в PHP-приложениях, пришло время погрузиться в некоторые практические примеры. Хотя теорию, лежащую в основе DTO, важно понимать, она может показаться немного суховатой без реального контекста.
- UserDTO создан статическим методом
class UserDTO { private int $id; private string $name; private string $email; private function __construct(int $id, string $name, string $email) { $this->id = $id; $this->name = $name; $this->email = $email; } public static function create(int $id, string $name, string $email): UserDTO { return new self($id, $name, $email); } public function id(): int { return $this->id; } public function name(): string { return $this->name; } public function email(): string { return $this->email; } }
В этом примере класс UserDTO
имеет три частных свойства: $id
, $name
и $email
. Конструктор сделан закрытым, чтобы гарантировать, что экземпляр класса может быть создан только с использованием статического метода create
.
Метод create
принимает три свойства в качестве аргументов и возвращает новый объект UserDTO
с этими свойствами. Методы id
, name
и email
обеспечивают доступ только для чтения к закрытым свойствам класса.
Использование частного конструктора и статического метода для создания класса помогает гарантировать, что данные в DTO действительны и могут использоваться по назначению, предотвращая при этом любые внешние манипуляции с данными.
Использование частных свойств и методов получения более традиционно и может использоваться в более ранних версиях PHP. Это позволяет вам определять свойства отдельно от конструктора, что может сделать код более модульным и простым для тестирования. Это также обеспечивает лучшую инкапсуляцию, поскольку свойства являются закрытыми и доступны только через методы получения. Однако для реализации этого подхода требуется больше кода, и он может быть менее кратким и удобочитаемым, чем подход public readonly
.
2. UserDTO, использующий общедоступный доступ только для чтения
class UserDTO { private function __construct( public readonly int $id, public readonly string $name, public readonly string $email ) {} public static function create(int $id, string $name, string $email): UserDTO { return new self($id, $name, $email); } }
Этот подход с использованием свойств public readonly
доступен только в PHP 8.1 и более поздних версиях. Это позволяет вам определять свойства непосредственно в сигнатуре конструктора, что может сделать код более кратким и удобным для чтения. Он также обеспечивает неизменность «из коробки», поскольку свойства являются общедоступными и доступны только для чтения. Однако этот подход не предоставляет каких-либо методов доступа к значениям свойств, что в некоторых ситуациях может быть недостатком.
Таким образом, оба подхода имеют свои преимущества и недостатки, и выбор между ними зависит от конкретных потребностей вашего приложения. Если вы используете PHP 8.1 или более позднюю версию и вам требуется неизменность, подход public readonly
может быть хорошим выбором. В противном случае подход с закрытыми свойствами и методами получения обеспечивает лучшую инкапсуляцию и может использоваться в более ранних версиях PHP.
В качестве бонуса, если вам интересно, как это работает с использованием трейтов. Пожалуйста, ознакомьтесь с моей другой статьей.