Sử dụng DTO trong Laravel

  • March 17, 2023
  • 1306

DTO là gì?

DTO là viết tắt của Data Transfer Object, là một design pattern sử dụng để trao đổi dữ liệu giữa các lớp khách nhau trong một ứng dụng. Dữ liệu trao đổi được đóng gói trong 1 đối tượng giúp việc trao đổi dữ liệu giữa các lớp minh bạch và dễ dàng.

Nhận biết DTO

Để nhận biết DTO, bạn có thể xem xét các đặc điểm sau:
  • Thường có các thuộc tính (properties) để lưu trữ dữ liệu.
  • Không chứa business logic hoặc xử lý dữ liệu.
  • Cung cấp các phương thức getter và setter để truy xuất và thiết lập giá trị của thuộc tính.
  • Thường được sử dụng trong quá trình giao tiếp với cơ sở dữ liệu hoặc các lớp trong hệ thống với nhau.

Sử dụng DTO trong laravel

DTO được sử dụng trong laravel với mục đích trao đổi dữ liệu giữa controller với service, service với repository. Giúp cho lớp data được tách biệt với business logic, làm module hoá ứng dụng dễ dàng bảo trì.

Tạo một lớp DTO để định nghĩa dữ liệu khi tạo mới một người dùng. Các thuộc tính của đối tượng user là thuộc tính trong class DTO.


namespace App\DTO;

class UserDTO
{
    public string $name;
    public string $email;
    public string $password;

    public function __construct(string $name, string $email, string $password)
    {
        $this->name = $name;
        $this->email = $email;
        $this->password = $password;
    }
}

Giờ chúng ta sẽ sử dụng DTO trong UserController như là một tham số truyền vào của hàm createUser().


namespace App\Http\Controllers;

use App\DTO\UserDTO;
use App\Services\UserService;
use Illuminate\Http\Request;

class UserController extends Controller
{
    private UserService $userService;

    public function __construct(UserService $userService)
    {
        $this->userService = $userService;
    }

    public function createUser(Request $request)
    {
        $userDTO = new UserDTO(
            $request->input('name'),
            $request->input('email'),
            $request->input('password')
        );

        $user = $this->userService->createUser($userDTO);

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

Làm như trên giúp dữ liệu được chuyển đổi một cách rõ ràng. Khi người dùng gửi request tạo user chúng ta chỉ lấy các input phục vụ cho việc tạo user để truyền vào service createUser().
Lúc này UserService chỉ việc sử dụng dữ liệu trong lớp DTO để tạo 1 người dùng mới, mà không cần phải quan tâm đến bất kì thứ gì trong request và controller.

Tạo UserService để create một user.


namespace App\Services;

use App\DTO\UserDTO;
use App\Models\User;

class UserService
{
    public function createUser(UserDTO $userDTO): User
    {
        $user = new User();
        $user->name = $userDTO->name;
        $user->email = $userDTO->email;
        $user->password = $userDTO->password;
        $user->save();

        return $user;
    }
}

Chúng ta cũng có thể tạo thêm một lớp Repository để tương tác với model.


public function createUser(UserDTO $userDto) {
    return $this->userRepository->create([
      'name' => $userDto->name,
      'email' => $userDto->email,
      // ... other fields
    ]);
  }

Trong bài viết này thì tương tác với model luôn ở service cho nhanh =)). Model sẽ sử dụng các dữ liệu trong lớp DTO để tạo mới 1 người dùng vào database.

Tổng kết

Như vậy là chúng ta đã sử dụng thành công design partten DTO vào dự án laravel. Viết như trên sẽ giúp ứng dụng trở lên module hoá hơn, mỗi một lớp sẽ thực hiện riêng một nhiêm vụ của mình, code clear, dễ trong việc viết unitest và maintain.