Laravel + Vue.js + DDDのすゝめ – Modelsとの付き合い方を考える

Laravel + Vue.js + DDDのすゝめ – Modelsとの付き合い方を考える

Laravelの標準では、「app/Models/」にLaravelのORマッパーである Eloquent(エロクアント) のモデルを配置します。
要はデータベースのテーブルと対になるオブジェクトです。

連載

本記事は複数記事の連載記事の1つです。

この記事に関連するコミット

DDDのエンティティとして使って良いのか?

エンティティはテーブルと対になるオブジェクトである必要はなく、アプリケーションとして意味のある単位としてあるべきです。(2つのテーブルから1つのエンティティとしてもOK)
また、Eloquentのモデルにはテーブル名やリレーション等の定義が入るため、一緒にしてしまうとドメインの責務と混ざってしまいます。

とは言え、 細かいことは良いんだ!軽量DDDだから似たようなもんだし使っちゃえ! といったようにモデルをエンティティとしても使いたくなりますが、辞めておいたほうが良いでしょう。

Userモデルで例を挙げると、継承しているEloquentのモデルクラスによって以下のようにデータベースのアクセス、プロパティへの値のセット、保存が出来ます。
つまり、Eloquentのモデルクラスによって何でもやりたい放題のエンティティになってしまいます。

このアプリはユーザー名は一度決めたら変えられない仕様なのでドメインでチェックして防ぎたいと思っても防ぎようがありません。

// データベースにアクセスしてID:1のユーザーを取得
$user = User::find(1);
// ユーザー名を変更
$user->name = 'changed name';
// データベースに変更内容を保存
$user->save();

ORマッパー用のモデルとエンティティを分ける

以下のディレクトリ構成でORマッパー用のモデルとエンティティを分けます。

種別 役割 ディレクトリ サンプル
ORマッパー用のモデル データベースへ読み書きするモデル app/Models OrderModel.php
エンティティ アプリケーションのビジネス知識を表現するモデル packages/domains Order.php

データベースから取得する流れ場合は、
データベース → ORマッパー用のモデル → エンティティと変換します。

データベースへ永続化する場合は、
エンティティ → ORマッパー用のモデル → データベースと変換します。

詳しくは別途リポジトリの記事に記載します。

ORマッパー用のモデルのディレクトリについて

Laravel経験者を採用してもフレームワークとしての標準から構成を変えるほど、学習コストが高くなってしまいます。
また、Artisanコマンドもパスが違うと使えなくなります。

そのため、サンプルではLaravel標準の「app/Models」にしています。

そのトレードオフとしてModelsだけレイヤーの概念から外れてLaravelディレクトリ郡にいることが違和感でもあるため、インフラストラクチャ層などに置いてしまっても構わないと思います。

オートローダーの設定

ルートディレクトリにpackagesディレクトリを追加し、Orderを追加しました。
php artisan tinkerコマンドでREPL(対話型コンソール)を立ち上げ、インスタンスを生成してみます。

Packages\Domains\Orders\Order::create('num');

「not found」とクラスが見つからないとエラーが表示されます。

PHP Error:  Class "Packages\Domains\Orders\Order();" not found in Psy Shell code on line 1

これは入力ミスなどではなく、PHPの名前・ディレクトリパスの解決をしてくれるオートローディングの対象ディレクトリに「packages」が含まれていないため発生します。

指定方法はcomposer.jsonの’autoload’に以下のように追加します。

composer.json

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/",
            "Packages\\": "packages/"
        }
    },

追加しただけではダメで、変更を反映するには以下のコマンドを実行します。

composer dump-autoload

プログラミングカテゴリの最新記事