تصویر یک کامیون با بار بیش از حد

DTO چیست و چگونه در لاراول از آن استفاده کنیم؟

filament-panels::layout.avatar.alt

علی گلکار

17 مهر 1402
4 دقیقه

DTO مخفف "Data Transfer Object" یه دیزاین پترن هست که برای جابه‌جایی اطلاعات بین لایه‌های مختلف برنامه استفاده می‌شه، نحوه کار DTO‌ها در واقع به اینصورت که اطلاعات توی یه "Object" نگه‌داری می‌شن و اون Object هست که بین قسمت‌های مختلف برنامه پاس داده می‌شه!

تصویر یک کامیون با بار بیش از حد
DTO تقریبن یه همچین چیزیه ؛)

در برنامه‌های لاراولی معمولا DTOها برای پاس دادن اطلاعات بین Repository و Service یا Service و Controller و امثالهم استفاده می‌شه. این مهم به ما کمک می‌کنه که بتونیم لاجیک برنامه رو حفظ کنیم و برنامه رو قابل توسعه نگه داریم.

استفاده از DTO در لاراول

برای استفاده از DTO توی برنامه لاراولی، نیازه که یه کلاس برای هر DTO که مورد استفاده قرار می‌دیم ایجاد کنیم، برای مثال فرض کنید که یه مدل Product داریم که property ‌های name، count، price رو شامل می‌شه.

در مسیر project_folder\app\DTO یه فایل به نام ProductDTO مشابه مثال زیر ایجاد می‌کنیم:

namespace App\DTO;

class ProductDTO
{
    public string $name;
    public int $count;
    public int $price;

    public function __construct(string $name, int $count, int $price)
    {
        $this->name = $name;
        $this->count = $count;
        $this->price = $price;
    }
}

DTO ما آمادست و می‌تونیم ازش استفاده کنیم، برای مثال برای ساخت یک محصول جدید کنترلرمون رو به این صورت ویرایش می‌کنیم:

namespace App\Http\Controllers;

use App\DTO\ProductDTO;
use App\Services\ProductService;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    private ProductService $productService;

    public function __construct(ProductService $productService)
    {
        $this->productService = $productService;
    }

    public function createProduct(Request $request)
    {
        $productDTO = new ProductDTO(
            $request->name,
            $request->count,
            $request->price
        );

        $product = $this->productService->createProduct($productDTO);

        return response()->json($product);
    }
}

توی مثال بالا متد CreateProduct  یک object به نام $request از سمت کلاینت دریافت می‌کنه و بر اساس اطلاعات اون یک Object به نام productDTO می‌سازه و به متد CreateProduct در ProductService پاسش می‌ده. ProdcutService الان می‌تونه بر اساس DTO که دریافت کرده یه محصول جدید رو توی دیتابیس ایجاد کنه.

فایده استفاده از این روش این هست که شما در صورتی که مثلا اگر به مدل Product یه property جدید اضافه کردید تنها کاری که لازمه انجام بدید اینه که به productDTO این property رو اضافه کنید و تمام...، نیاز نیست همه جارو ویرایش کنید و خودکار به همه قسمت ها اضافه می‌شه. در نتیجه برنامه ماژولار و توسعه پذیری دارید.

اگر بخوایم توی این آموزش پترن ریپوزیتوری (repository pattern) رو نادیده بگیریم و از داخل سرویس مستقیم مدل رو فراخوانی کنیم و یک محصول جدید بسازیم، به این صورت می‌تونیم عمل کنیم:

namespace App\Services;

use App\DTO\ProductDTO;
use App\Models\Product;

class ProductService
{
    public function createProduct(ProductDTO $productDTO): Product
    {
        $product = new Product();
        $product->name = $productDTO->name;
        $product->count = $productDTO->count;
        $product->price = $productDTO->price;
        $product->save();

        // OR

        $product = Product::create($productDTO);

        return $product;
    }
}

در کد بالا $productDTO رو که به متد createProduct پاس داده بودیم رو دریافت کردیم و داخل متد، DTO رو به مدل Product اساین کردیم. به همین سادگی

دلیل اینکه توی این پست از Repository Design Pattern استفاده نکردیم ساده تر کردن مفهوم آموزش بود وگرنه شما می‌تونید همونطور که DTO رو به سرویس پاس دادید به ریپوزیتوری هم پاسش بدید و اونجا فرایند ذخیره سازی رو انجام بدید.

البته می‌تونید برای اعمال مختلف DTO های جداگانه‌ای ایجاد کنید برای مثال به صورت زیر DTO ها رو خرد کنید:

  • Create product = DTO/Product/CreateProductDTO
  • Update product = DTO/Product/EditProductDTO
  • Get product = DTO/Product/ViewProductDTO
  • و...

پایان/

 

© 1403 علی گلکار، تمام حقوق مادی و معنوی محفوظ است.

\
شما آفلاین هستید!