iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 20
0
Modern Web

全端成長之旅系列 第 20

Day.20 Laravel with DDD Part.1

為了讓 laravel 更貼近 DDD 的架構,會需要調整一些 Laravel 的專案架構,這部分你必須熟悉 Laravel 的容器運作、生命週期,如果你還不熟悉,建議先讀過 Laravel 原始碼分析

還有,接下來的內容會假設你對 DDD 已經有一定程度的理解,如果還沒有,建議先讀過 Think in Domain-Driven Design


Laravel 專案所有最被關注的東西都放在 app 資料夾底下,這件事就已經跟 DDD 的 Domain、Bounded Context 牴觸了,我個人是額外建立一個新的命名空間(資料夾)來放不同 Bounded Context 的程式,裡面每一個子目錄內容都跟原本 app 裡的架構差不多,原本 app 裡面有的 Http、Services、Providers ... 的目錄,在各個 Bounded Context 內都有。

這個部分可以考慮使用 laravel-modules 來實現類似的目的,如果你跟我一樣不想裝這個套件,那會比較辛苦一點,因為你需要寫一些 Provider 把各個 Bounded Context 內的 migrations、routes、configs .... 的程式在初始化時註冊到 laravel 中。

現在你的專案架構應該會像這樣:

  • app/
    • Http/
    • Services/
    • Providers/
    • User.php
    • .... 其他目錄、檔案
  • modules/
    • ModulesA
      • Http/
      • Services/
      • Providers/
      • Database/
      • Tests/
      • ... 其他目錄、檔案
    • ModulesB
      • Http/
      • Services/
      • Providers/
      • Database/
      • Tests/
      • ... 其他目錄、檔案
    • 其他 Module...
  • bootstrap/
  • public/
  • storage/
  • .... 其他檔案、目錄

modules 目錄裡的各個 module 其實就是對應到一個 Bounded Context,當然你想要用別的命名也是可以,總之目的是要把系統要解決的問題切分開來。

這邊附上我的 AppServiceProvider 的片段,給大家參考:

<?php

namespace App\Providers;

use File;
use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Factory;

class AppServiceProvider extends ServiceProvider
{
    // .... 省略

 protected function registerEloquentFactories()
    {
        // 預設 factories 如果有用到記得載入,或是乾脆不要用
        $this->app->make(Factory::class)->load(base_path('database/factories'));

        foreach (config('modules') as $module) {
            $moduleFactoriesDir = base_path('modules/' . $module['name'] .'/Database/factories');
            if (File::isDirectory($moduleFactoriesDir)) {
                $this->app->make(Factory::class)->load($moduleFactoriesDir);
            }
        }
    }

    protected function reqisterMigrations()
    {
        $directories = [
            // 預設 migration 如果有用到記得載入,或是乾脆不要用
            base_path('database/migrations')
        ];
        
        foreach (config('modules') as $module) {
            $moduleMigrationsDir = base_path('modules/' . $module['name'] .'/Database/migrations');
            if (File::isDirectory($moduleMigrationsDir)) {
                array_push($directories, $moduleMigrationsDir);
            }
        }

        $this->loadMigrationsFrom($directories);
    }
}

}

上面那段程式的思路很簡單,其實就是建立一個 modules config,每當有新的 module(Bounded Context) 時,就在 modules config 裡增加一組設定,然後 AppServiceProvider 在 register 的時候把該載入的內容載入好。


上一篇
Day.19 後端的開始
下一篇
Day.21 Laravel with DDD Part.2
系列文
全端成長之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言