役立つ情報
登録日: 2025-02-02   最終更新日: 2025-03-19

Laravel に DDD の概念を取り込む

Laravel に DDD(ドメイン駆動設計)の概念を取り込むには、アーキテクチャの工夫が必要です。Laravel はもともと MVC(Model View Controller)をベースとしたフレームワークですが、DDD の概念を適用することで、よりスケーラブルで保守性の高いアプリケーションを構築できます。

DDDをLaravelに適用する際のポイント

レイヤー構成の見直し

DDDでは以下のようなレイヤー構成を採用します。 Laravel の MVC にそのまま適用するのではなく、適切にレイヤーを分割しましょう。

ドメイン層(Domain Layer)

  • エンティティ(Entities)
  • 値オブジェクト(Value Objects)
  • ドメインサービス(Domain Services)
  • 集約(Aggregates)
  • リポジトリインターフェース(Repository Interface)
  • アプリケーション層(Application Layer)

アプリケーションサービス(Application Services)

  • DTO(Data Transfer Objects)
  • インフラストラクチャ層(Infrastructure Layer)

リポジトリの実装(Eloquent など)

  • 外部 API やデータベースとの接続
  • プレゼンテーション層(Presentation Layer)

コントローラー(Controllers)

  • リクエスト(Requests)
  • ビュー(Views)

ドメイン層の実装

エンティティ

エンティティは、識別子(ID)を持ち、ビジネスルールを適用するオブジェクトです。


namespace App\Domain\Entities;

class User
{
    private string $id;
    private string $name;
    private string $email;

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

    public function changeName(string $name): void
    {
        $this->name = $name;
    }

    public function getId(): string
    {
        return $this->id;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getEmail(): string
    {
        return $this->email;
    }
}

値オブジェクト

値オブジェクトは不変で、ビジネスルールをカプセル化します。


namespace App\Domain\ValueObjects;

class Email
{
    private string $email;

    public function __construct(string $email)
    {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new \InvalidArgumentException("Invalid email");
        }
        $this->email = $email;
    }

    public function getValue(): string
    {
        return $this->email;
    }
}

アプリケーション層

アプリケーション層では、ユースケースを実装します。


namespace App\Application\Services;

use App\Domain\Repositories\UserRepositoryInterface;
use App\Domain\Entities\User;

class UserService
{
    private UserRepositoryInterface $userRepository;

    public function __construct(
            UserRepositoryInterface $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function registerUser(string $name, string $email): User
    {
        $user = new User(uniqid(), $name, $email);
        $this->userRepository->save($user);
        return $user;
    }
}

インフラストラクチャ層

リポジトリをEloquentを用いて実装します。


namespace App\Infrastructure\Repositories;

use App\Domain\Repositories\UserRepositoryInterface;
use App\Domain\Entities\User;
use App\Models\User as EloquentUser;

class UserRepository implements UserRepositoryInterface
{
    public function save(User $user): void
    {
        EloquentUser::create([
            'id' => $user->getId(),
            'name' => $user->getName(),
            'email' => $user->getEmail()
        ]);
    }
}

コントローラー(プレゼンテーション層)

コントローラーはアプリケーション層のサービスを呼び出します。


namespace App\Http\Controllers;

use App\Application\Services\UserService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;

class UserController extends Controller
{
    private UserService $userService;

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

    public function register(Request $request): JsonResponse
    {
        $user = $this->userService->registerUser(
                    $request->input('name'),
                    $request->input('email')
                );
        return response()->json([
                    'id' => $user->getId(),
                    'name' => $user->getName(),
                    'email' => $user->getEmail()
                ]);
    }
}

まとめ

Laravel に DDD を適用するには、以下のポイントを意識すると良い。

  • レイヤードアーキテクチャを採用する(ドメイン層・アプリケーション層・インフラ層・プレゼンテーション層)
  • エンティティと値オブジェクトを活用して、ビジネスルールをカプセル化する
  • リポジトリパターンを導入し、データアクセスの抽象化を行う
  • アプリケーションサービスを通じて、ユースケース単位でビジネスロジックを実装する

Copyright 役立つ情報.net