bypassflow / domain-kit
Modeling primitives that eliminate implementation noise by abstracting object interning, immutability, and collection integrity.
Installs: 1
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 1
Forks: 0
Open Issues: 4
pkg:composer/bypassflow/domain-kit
Requires
- php: >=8.4.0
- ext-hash: *
- ext-mbstring: *
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.68
- phpunit/phpunit: ^12.0
README
domain-kitは、PHP8.4以降で動作するPHPでのドメイン駆動開発(DDD)をサポートするユーティリティパッケージです。
Requirements
- PHP 8.4 以上
- ext-hash
- ext-mbstring
バージョニング方針 (Versioning Policy)
本パッケージのバージョン番号は、ターゲットとするPHPバージョンを内包しています。
[PHP Version][Library Version]
- 804.x.x: PHP 8.4+ 向け
- 805.x.x: PHP 8.5+ 向け(予定)
これにより、言語アップデートに伴う破壊的変更とライブラリの進化を明確に分離します。
インストール (Installation)
Composerを使用してインストールします。本パッケージのバージョニング方針に基づき、使用しているPHPバージョンに合わせた制約を指定してください。
# PHP 8.4環境の場合
composer require bypassflow/domain-kit:^804.0
composer.json に直接記述する場合:
{
"require": {
"bypassflow/domain-kit": "^804.0"
}
}
Interning (InternableTrait)
InternableTraitを使用することで、Value Objectなどの「値によって同一性が定義されるオブジェクト」のInterning(インターン化)を容易に実現できます。
概要
Interning(インターン化)とは、同じパラメータを持つオブジェクトに対して常に同一のインスタンスを再利用する仕組みです。
- インスタンスの一意性保証:同一パラメータでintern()を呼び出すと、常に同じインスタンスが返されます。
cache_keyプロパティは読み取り専用で公開され、外部から識別子として利用可能です。
厳格な型判定:高速なハッシュアルゴリズムxxh128を用い、型情報を維持したままキーを生成します。
使い方
1. インターフェースの実装と Trait の使用
InternableInterfaceを実装し、InternableTraitをuseします。
use bypassflow\DomainKit\SharedKernel\Interning\contract\InternableInterface; use bypassflow\DomainKit\SharedKernel\Interning\contract\InternableTrait; class UserRole implements InternableInterface { use InternableTrait; private function __construct( private string $roleName, private int $level ) {} public static function of(string $roleName, int $level): self { // intern() メソッドでインスタンスを集約 return self::intern($roleName, $level); } }
2. インスタンスの取得と同一性
intern() メソッドを経由することで、メモリ内プールから既存のインスタンスが取得されます。また、Internable なオブジェクトをプロパティに持つ場合、そのキャッシュキーを再利用して自身のキーを構成します。
$admin1 = UserRole::of('admin', 10); $admin2 = UserRole::of('admin', 10); var_dump($admin1 === $admin2); // true (同一インスタンス) // キャッシュキーの参照 (PHP 8.4 Property Hooks) echo $admin1->cache_key; // 例:"54f3..." (xxh128 ハッシュ) $role = UserRole::of('admin', 10); // インターン化されたオブジェクトを引数に渡しても、正しく同一性が判定される $user = UserProfile::of('Alice', $role);
3. 属性による識別属性の定義 (IdCriteria)
IdCriteria 属性を使用することで、オブジェクトのどのプロパティを識別子として扱うかを宣言的に定義できます。これにより、オブジェクト全体を intern() に渡すだけで、自動的に最適なキーが抽出されます。
use bypassflow\DomainKit\SharedKernel\Interning\attribute\IdCriteria; class UserId implements InternableInterface { use InternableTrait; public function __construct( #[IdCriteria(alias: 'id', formatter: 'strtolower')] private string $value ) {} public static function of(string $value): self { // オブジェクト自身を渡すと、アトリビュートに基づき識別値が抽出される return self::intern(new static($value)); } }
- alias: 識別子の論理名(将来的な拡張用)。
- groups: 特定のコンテキストでのみ識別値として扱う場合に指定(デフォルトは default)。
- formatter: 値を抽出する際の変換処理(strtolower やカスタム関数など)を指定可能。
技術仕様
ハッシュ生成ロジック (updateHashContext)
xxh128 アルゴリズムを使用し、以下のルールで型を厳格に区別してキーを生成します。
- スカラ値:string, int, float はそれぞれの型情報を付与して区別します(例:s, i, d)。
- 論理値/NULL:boolはb1/b0、nullはnとして扱われます。
- 配列:要素数、キー、値を再帰的に評価します。
- オブジェクト
InternableInterface実装クラス:そのオブジェクトの$cache_keyを再利用します。- IdCriteria 属性を持つクラス: 初回アクセス時に「抽出プラン」をコンパイルし、2回目以降はリフレクションを一切使わず、特定のプロパティ値のみを高速に抽出してハッシュ化します。
- 一般的なオブジェクト:インスタンスID (
spl_object_id) で識別します。
- リソース/その他:シリアライズまたは型情報を用いて識別します。
再帰深度の制限
深い階層の配列によるスタックオーバーフローを防ぐため、再帰深度の上限が設けられています。
- デフォルト上限:1024
カスタマイズ:クラス定数INTERN_RECURSION_LIMITを定義することで変更可能です。
実行プランのコンパイルとキャッシュ
リフレクションによるアトリビュート解析は高コストであるため、本パッケージでは「コンパイル&キャッシュ」方式を採用しています。
- 初回解析: クラス・グループごとにどのプロパティを抽出すべきかを解析。
- 2回目以降: 解析済みの「実行プラン」に基づき、通常のプロパティアクセスのみでデータを抽出。
- バイパス機構: 属性を持たないクラスは一度のチェックで「解析不要」とマークされ、以降は
spl_object_idによる最速パスへ流れます。
プールのクリア
長時間実行されるプロセスなどでメモリを解放したい場合、プールを全消去できます。
// 特定クラスのインスタンスプールをクリア UserRole::purge();
拡張性 (Interning Strategy)
内部ではStaticArrayStrategyをベースとしたロジックが採用されており、InterningStrategyInterfaceを通じて将来的に永続化や外部キャッシュへの差し替えが可能な設計になっています。