はじめに
Laravel で巨大なプロジェクトを作っていくと、大量のフォルダとファイルで押しつぶされてしまいますよね....。
というときにローカルパッケージを使った開発はどうか?という提案記事です。
検討したソフトウェアアーキテクチャ
- モノリス
- 一つのプロジェクトに全ての機能を実装する、いわゆる普通の作り方
- Laravelを使うとこうなりがち...
- そして、フォルダが肥大化しがち...
- マイクロサービス
- 機能ごとに別のプロジェクトに分けて、連携させるやり方
- 負荷分散ができるため、サービスの最終系としてはベスト
- ただコストが無視できないので、気軽には始められない...
- モジュラモノリス
- 一つのプロジェクトの中で、機能ごとにコードを分離する作り方
- モノリスとマイクロサービスの良いとこ取り
- laravel-modules で実現可能
- 良い選択!
- (参考) DDD ドメイン駆動設計
- ビジネスを中心に考え、システムを作るスタイル(レイヤードアーキテクチャ)
- 使用する Entity や UseCase などを明確に作成する
- モデリングがたいへん...コードも山盛り...大規模向け...
- Laravel の提供する構造をほぼ全て無視するため、Laravelでやる必要があるのか?から抜け出せない...
DDDが導入出来たらスバラシイと思うのだが、伝達コストなど、様々な属性・能力が集まるチームで進められるか?を考えると少し躊躇する...。(司令塔と、無限の余裕がほしい)
次点として モジュラモノリス
を仮で導入した。
これは、システム開発のとても良い着地点だと思う。
しかし、route や migration など、Laravel の機能全てが分離されるため、責務が分けにくいやつらが出てくる。
また、モジュール間の繋がりも書きにくい。
加えて、パッケージへの依存度が非常上がるので、メンテナンスされなくなると〇ぬデメリットがある。
ローカルパッケージ戦略
そこで、機能ごとにモジュールを別のパッケージとして記載し、プロジェクトに組み込むのはどうかと考えた。
モジュラモノリスの、ローカルパッケージ版である。
汎用的な、例えば印刷するモジュールを、パッケージとして本体のプロジェクトから切り出すイメージです。
アーキテクチャのイメージはこんな感じ。
-
Main Project
は、ルーティングや権限を管理する -
Sub Package
は、機能、ビジネスロジックを提供する
こうすることで、各部分の責務が明確になり、見通しの良いコードになると考えた。
全体のルーティングや、モジュール間の繋がりは、mainに書くことでぱっと見で管理しやすい。
なお、Laravel の Package は、書こうと思えばルーティングまで全て書くことができるので、モジュラモノリスと同じように利用することもできます。
パッケージ化することで、そこだけ別タスクとして切り出したり、丁寧にテストを書いて封印し、品質を保証するなど、様々な利点がありそうです。
導入
必要なもの:
-
php
composer
コマンドが動作する環境 - ある程度のLaravelの知識 (触れません)
※ 焦点をブラさないため、 Docker は使いません
今回はこんな感じの構成にします。
laravel-local-package
├ app
├ ...
+ ├ package
+ │ ├ sub-module
+ │ ├ ...
├ ...
Main Project
が laravel-local-package
という名前。
Sub Package
が sub-module
という名前。
Main Project
の作成
既にあるものを利用しても大丈夫です。
$ php -v
PHP 8.2.0 (cli) (built: Nov 27 2023 09:22:06) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.0, Copyright (c) Zend Technologies
$ composer -V
Composer version 2.6.5 2023-10-06 10:11:52
# laravel install
$ composer create-project laravel/laravel laravel-local-package "11.*" --prefer-dist
$ cd laravel-local-package
$ php artisan serve
=> http://127.0.0.1:8000
が表示されたらOK
Sub Package
の作成
Laravel でパッケージを作成する場合、Spatie
神のテンプレートを使うのが最も簡単。
このテンプレート自体はMITライセンスだが、有償のトレーニング動画 が用意されている。
# create package
$ git clone https://github.com/spatie/package-skeleton-laravel ./package/sub-module
$ cd ./package/sub-module
# もし PHP v8.2 を使用する場合は、コミットを切り替える (上記は PHP v8.4 推奨)
# 他のバージョンは以下から探す
# ref: https://github.com/spatie/package-skeleton-laravel/commits/main/
#
$ git checkout 9d60f35
# git in git になって使いにくいので、好みで git を消す
$ rm -rf ./.git
準備ができたら configure.php
でパッケージの初期設定を行う。
項目は <name> (<username>, <email@xxx.com>)
で対応している。
パッケージ名は <Vendor namespace>/<Package name>
となる。
Author
は作成者、Vendor
は社名を入れればよい。
未入力の場合、かっこの中身がそのまま登録される。
今回はローカルパッケージなので、まぁ適当でも問題ない。
PhpStan と Pint は入れておこう。
空欄があると composer install
でコケるので注意! (しかも分かりにくい)
$ php ./configure.php
Author name (xxx): sigeta
Author email (xxx): sigeta@example.com
Author username: sigeta
Vendor name (xxx): crest
Vendor username (xxx): crest
Vendor namespace (Crest):
Package name (sub-module):
Class name (SubModule):
Package description (This is my package sub-module):
Enable PhpStan? (Y/n): Y
Enable Laravel Pint? (Y/n): Y
Enable Dependabot? (Y/n): n
Use Ray for debugging? (Y/n): n
Use automatic changelog updater workflow? (Y/n): n
Modify files? (Y/n): Y
Execute `composer install` and run tests? (y/N): y
Let this script delete itself? (Y/n): Y
Let this script delete itself?
まで表示されたら導入完了。
Main Project
に Sub Package
を紐づける
main の composer.json
に、このパッケージを紐づける。
プロジェクトルートにディレクトリを移動して、
$ cd ../../
$ composer config repositories.local path ./package/sub-module
$ composer require "crest/sub-module @dev"
パッケージ名が分からない場合は、パッケージ側の composer.json
の name
キーを読む。
@dev
を付けることで、vendor
にシンボリックリンクが張られ、リアルタイムで変更が読み取られる。
もちろんモジュールは git で管理することもできる。
参考: Repositories - Composer
動作確認
コマンドが用意されているので、疎通確認として main で実行する。
package/sub-module/src/Commands/SubModuleCommand.php
$ php artisan sub-module
All done
パッケージの開発ガイド
あまりにも長くなったので、次の記事へ
公開次第リンク:【Laravel】ローカルパッケージを利用した開発戦略 その2:実践編