برنامه نویس فان | Fun Developer یک آدم ساده که عاشق برنامه نویسی و کد زدنه :) تلاش میکنه تا به بقیه کمک کنه. توسعه دهنده هسته لاراول و فضای اوپن سورس. فاندر پرانتز و کد نیوز.
در این پست قراره درباره DTO در پی اچ پی صحبت کنیم. در اپلیکیشن های مدرن یکی از بهترین راه ها برای انتقال داده روش DTO (Data Transfer Object) هست. در ادامه در مورد مزایا و روش پیاده سازیش صحبت خواهیم کرد.
DTO چیه؟
در واقع DTO یک پترن برای کپسوله سازی کردن دیتا های ما هست و ما با یک قالب خاص و مشخص داده ها بین لایه های اپلیکیشن جا به جا میکنیم. فرض کنید یک دستگاه درب باز کن دارید، این دستگاه یک قالب خاص درب باز میکنه و شما باید یک جوری این قالب رو آماده کنید تا درب باز کنه و این کار دقیقا کاریه که DTO توی اپلیکیشن ما انجام میده.
دلیل استفاده از DTO چیه؟
1. Type Safety
یکی از دلایلی که شما نیاز به DTO دارید این هست که مقدار های دیتا ما امنیت دارند و باعث کرش به هیچ عنوان نمیشه:
// Without DTO - Prone to errors
function processUser($data) {
$name = $data['name']; // What if 'name' doesn't exist?
$email = $data['email']; // What if it's not a valid email?
}
// With DTO - Type-safe and clear
function processUser(UserDto $data) {
$name = $data->name; // IDE autocompletion works
$email = $data->email; // Property is guaranteed to exist
}
2. Code Clarity
در واقع DTO باعث میشه که از خطا پرهیز کنید و همینطور باعث autoload شدن IDE شما میشه. همینطور برای خودش یک جور مستندات هم هست!
3. Clean and Maintainable
این پترن کد شما به صورت زیادی تمیز میکنه و همینطور قابل نگهداری هست. این پترن کد شما قابل ریفکتور میکنه و ساختار کدتون از منطق اپلیکیشن جدا میکنه.
4. Enhanced Security Through Type Hinting
با استفاده از type hinting شما امنیت کدتون بیشتر میکنید و خطا احتمالی در کدتون کمتر کمتر میکنید همینطور اعتبارسنجی هم میتونید در سطح DTO انجام بدید.
5. Performance Optimization
با استفاده از این پترن شما میتونید پرفورمنس کدتون بیشتر کنید شاید سوال باشه چرا بهتر میشه؟ به دلیل اینکه شما فیلد های کمتر و خاص انتخاب میکنید همینطور از کوئری های الکی به دیتابیس جلوگیری میشه و قابلیت کشینگ در DTO دارید.
6. Improved Testability
با استفاده از این پترن شما میتونید خیلی بهتر تست نویسی انجام بدید و قابلیت ماک کردن (mock) در تست ها دارید.
پیاده سازی DTO
خب برای شروع یک فایل درست کنید به نام UserDto.php و یک متد به نام "fromRequest" درست کنید:
use Illuminate\Http\Request;
class UserDto
{
public function __construct(
public readonly string $name,
public readonly string $email,
public readonly ?string $address,
public readonly DateTime $createdAt = new DateTime()
) {}
public static function fromRequest(Request $request): self
{
return new self(
name: $request->input('name'),
email: $request->input('email'),
address: $request->input('address'),
);
}
}
در اینجا ما پراپرتی name, email, address, created_at داریم و اینها میشه دیتا هایی که بین آبجکت ها جا به جا میشن.
حالا ما میتونیم یک حرکت جذاب بزنیم و اونم این هست که بیایم اعتبارسنجی هم داخل DTO انجام بدیم:
use Illuminate\Http\Request;
use Illuminate\Validation\ValidationException;
class UserDto
{
public function __construct(
public readonly string $name,
public readonly string $email,
public readonly ?string $address,
) {
$this->validateEmail();
}
public static function fromRequest(Request $request): self
{
$validated = $request->validate([
'name' => ['required', 'string', 'max:100'],
'email' => ['required', 'email', 'max:200'],
'address' => ['nullable', 'string', 'max:500'],
]);
return new self(
name: $validated['name'],
email: $validated['email'],
address: $validated['address'] ?? null,
);
}
private function validateEmail(): void
{
if (!filter_var($this->email, FILTER_VALIDATE_EMAIL)) {
throw new ValidationException('Invalid email format');
}
}
}
شما بازم میتونید خیلی کار ها اینجا انجام بدید، این به خودتون بستگی داره.
مثال واقعی از DTO
خب حالا ما میتونیم از همین DTO که ساختیم بیایم در دنیای واقعی استفاده کنیم. در این مثال ما یک کاربر میسازیم با استفاده از DTO و سرویس ها:
// Controller
public function createUser(Request $request)
{
$userDto = UserDto::fromRequest($request);
// DTO guarantees type safety and data validity
$user = $this->userService->createUser($userDto);
return response()->json($user);
}
// Service
public function createUser(UserDto $dto): User
{
// Safely access validated and typed properties
return User::create([
'name' => $dto->name,
'email' => $dto->email,
'address' => $dto->address,
]);
}
نتیجه گیری
در آخر شما احتمال زیاد به این نتیجه رسیدید که این پترن خداست و یک حس تمیزی و راحت بودن دارید. این پترن خیلی خوبه و به نظرم حتما توی پروژه هاتون یک بار هم شده پیاده کنید و در عمل ببینید چطوره.
اولین نفر باش که نظر ثبت میکنی :) یعنی یه کامنت به ما نمیرسه 😁