Laravelでドメイン駆動設計(DDD)を実装する際のサンプルコード

Laravel

Laravelでドメイン駆動設計(DDD)を取り入れるためのサンプルコードを紹介します。

ディレクトリ構造

app
├── Console
├── Domain
│   ├── Models
│   │   └── User.php
│   ├── Repositories
│   │   └── UserRepositoryInterface.php
│   └── Services
│       └── UserService.php
├── Exceptions
├── Http
│   ├── Controllers
│   │   └── UserController.php
│   ├── Middleware
│   └── Requests
├── Infrastructure
│   ├── Eloquent
│   │   ├── Models
│   │   │   └── EloquentUser.php
│   │   └── Repositories
│   │       └── EloquentUserRepository.php
└── Providers
    └── AppServiceProvider.php

<?php

namespace App\Domain\Models;

class User
{
    public int $id;
    public string $name;
    public string $email;

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

<?php

namespace App\Domain\Repositories;

use App\Domain\Models\User;

interface UserRepositoryInterface
{
    public function find(int $id): ?User;
}

<?php

namespace App\Domain\Services;

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

class UserService
{
    private UserRepositoryInterface $userRepository;

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

    public function findUser(int $id): ?User
    {
        return $this->userRepository->find($id);
    }
}

<?php

namespace App\Infrastructure\Eloquent\Models;

use Illuminate\Database\Eloquent\Model;

class EloquentUser extends Model
{
    protected $table = 'users';

    protected $fillable = [
        'name',
        'email',
    ];
}

<?php

namespace App\Infrastructure\Eloquent\Repositories;

use App\Domain\Models\User;
use App\Domain\Repositories\UserRepositoryInterface;
use App\Infrastructure\Eloquent\Models\EloquentUser;

class EloquentUserRepository implements UserRepositoryInterface
{
    public function find(int $id): ?User
    {
        $eloquentUser = EloquentUser::find($id);

        if ($eloquentUser === null) {
            return null;
        }

        return new User(
            $eloquentUser->id,
            $eloquentUser->name,
            $eloquentUser->email
        );
    }
}

<?php

namespace App\Http\Controllers;

use App\Domain\Services\UserService;
use Illuminate\Http\Request;

class UserController extends Controller
{
    private UserService $userService;

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

    public function show(int $id)
    {
        $user = $this->userService->findUser($id);

        if ($user === null) {
            return response()->json(['message' => 'User not found'], 404);
        }

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

<?php

namespace App\Providers;

use App\Domain\Repositories\UserRepositoryInterface;
use App\Domain\Services\UserService;
use App\Infrastructure\Eloquent\Repositories\EloquentUserRepository;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->bind(UserRepositoryInterface::class, EloquentUserRepository::class);
        $this->app->bind(UserService::class, UserService::class);
    }

    public function boot()
    {
        //
    }
}

<?php

use App\Http\Controllers\UserController;
use Illuminate\Support\Facades\Route;

Route::get('/users/{id}', [UserController::class, 'show']);

この例では、ユーザー情報を取得する機能を実装していますが、他の機能も同様に実装できます。ドメイン層、アプリケーション層、インフラストラクチャ層の役割を理解し、適切に分割することで、保守性や拡張性の高いアプリケーションを実現できます。

コメント

タイトルとURLをコピーしました