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