آموزش DTO (Data Transfer Object) در پی اچ پی

در این پست قراره درباره 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,
    ]);
}

نتیجه گیری

در آخر شما احتمال زیاد به این نتیجه رسیدید که این پترن خداست و یک حس تمیزی و راحت بودن دارید. این پترن خیلی خوبه و به نظرم حتما توی پروژه هاتون یک بار هم شده پیاده کنید و در عمل ببینید چطوره.

0 🔥
0 🎉
0 😮
1 👍
0 💜
0 👏
میلاد خسروی
نویسنده کد نیوز

برنامه نویس فان | Fun Developer یک آدم ساده که عاشق برنامه نویسی و کد زدنه :) تلاش میکنه تا به بقیه کمک کنه. توسعه دهنده هسته لاراول و فضای اوپن سورس. فاندر پرانتز و کد نیوز.

0+ نظر

برای ثبت نظر ابتدا ورود کنید.

0 نظر

    اولین نفر باش که نظر ثبت میکنی :) یعنی یه کامنت به ما نمیرسه 😁