メインコンテンツまでスキップ

Weaver ORM とは?

Weaver ORM は、Symfony アプリケーション向けの PHP 8.4 以上対応のオブジェクト関係マッパー(ORM)です。単一の原則に基づいて構築されています:ドメインオブジェクトはデータベースについて一切知識を持つべきではない。エンティティクラスへのアノテーション不要、プロキシ生成不要、実行時リフレクション不要 — 純粋な PHP オブジェクトと、それらを SQL に変換する明示的なマッパークラスだけで構成されています。

Weaver が解決する問題

Doctrine のプロキシオブジェクト

Doctrine はすべての関連エンティティをプロキシクラスでラップし、プロパティへのアクセスを傍受して初回アクセス時に SQL クエリを実行します。従来のリクエスト/レスポンスサイクルでは見えませんが、N+1 クエリパターンを暗黙的に引き起こし、デバッグを困難にします(var_dump($post->getAuthor()) はユーザーではなくプロキシを出力します)。

長期稼働する PHP ワーカー(RoadRunner、FrankenPHP、Swoole、Symfony Messenger)では、EntityManager がリクエスト間で古い状態を蓄積し、リクエスト境界ごとに手動でリセットする必要があります — これは見逃しやすく、診断が難しいバグを引き起こします。

リフレクションベースのハイドレーション

Doctrine は ReflectionProperty を使用してエンティティオブジェクトのプライベート/プロテクトプロパティを直接設定し、ドメインロジックを迂回します。リクエストごとに PHP アトリビュートを再パースするか、ウォームキャッシュを参照する必要があり、プロキシクラスはディスク上に存在しなければなりません。

無制限のアイデンティティマップ

Doctrine の EntityManager はリクエストの間、ロードしたすべてのエンティティをメモリに保持します。大量の結果セットをロードすると、メモリが際限なく増大します。回避策である $em->clear() は、再永続化し忘れたエンティティも含め、すべてをデタッチしてしまいます。

Weaver の違い

Weaver は4つの原則に基づいて構築されています:

  1. エンティティとしての純粋な PHP オブジェクト。 User クラスは ORM への依存をゼロにします。アトリビュート不要、基底クラス不要、インターフェース不要。Symfony を起動したりデータベースに接続したりすることなくユニットテスト可能な、純粋な値オブジェクトまたはドメインオブジェクトです。

  2. 明示的なマッパークラス。 独立した UserMapper クラスが、Userusers テーブルにどのようにマップするかを記述します。カラム型、リレーション、プライマリキー — すべて一か所に、すべて純粋な PHP で、完全に grep 可能で静的解析可能です。

  3. プロキシなし、暗黙的な遅延ロードなし。 リレーションは常に ->with(['relation']) を通じて明示的にロードされます。どの SQL がいつ実行されるかを常に把握できます。

  4. ワーカーセーフな設計。 マッパーはステートレスで、ワーカープロセスごとに一度ロードされます。各 HTTP リクエストまたは Messenger ジョブは独自の EntityWorkspace(作業単位)を持つため、リクエスト間での共有ミュータブル状態はありません。

主要な差別化ポイント

機能Doctrine ORMWeaver ORM
プロキシクラスの生成必要不要
実行時リフレクションありなし
遅延ロード暗黙的(プロキシ)明示的のみ
エンティティアノテーション/アトリビュートエンティティクラス上独立したマッパークラス
リセット時のワーカープロセス再起動必要不要
N+1 防止手動 JOIN FETCHwith() によって強制
10k 行あたりのメモリ〜48 MB〜11 MB
10k 行のハイドレーション時間〜420 ms〜95 ms
PHPStan /静的解析部分的(マジックプロキシ)完全(明示的マッパー)

ベンチマーク:PHP 8.4、PostgreSQL 16、Ubuntu 22.04、Profile リレーションを持つ 10,000 件の User 行。結果はハードウェアとクエリの複雑さによって異なります。

アーキテクチャの概要

エンティティ(純粋な PHP クラス — ORM への結合ゼロ)

└── マッパー(テーブル名、カラム、リレーション、hydrate/extract)

└── EntityWorkspace → QueryBuilder → PDO/DBAL

EntityWorkspace は Doctrine の EntityManager を置き換えます。これはリクエストスコープの作業単位で、flush() が呼ばれたときにどのエンティティを挿入、更新、または削除する必要があるかを追跡します。リクエストスコープであるため、リクエスト間でアイデンティティマップがリークすることはありません。

PyroSQL サポート

Weaver は PyroSQL(高性能なインプロセス分析 SQL エンジン)のオプションサポートを提供しています。PyroSQL は、プライマリリレーショナルデータベースに触れることなく、集計クエリ、レポーティング、大規模データセット操作のためのリードレプリカとして使用できます。詳細は PyroSQL セクション を参照してください。

要件

依存関係最小バージョン
PHP8.4
Symfony7.0
doctrine/dbal4.0(接続レイヤーのみ)
MySQL8.0
PostgreSQL14
SQLite3.35

オプション:

  • symfony/messenger — 非同期イベントパブリッシュとアウトボックスパターン
  • symfony/cache — クエリ結果キャッシング
  • mongodb/mongodb + ext-mongodb — MongoDB ドキュメントマッパーサポート

Weaver でないもの

Weaver は Doctrine のドロップイン代替品ではありません。Doctrine の DQL、クライテリア API、またはアトリビュートベースのマイグレーションに強く依存している場合、そのレイヤーを書き直す必要があります。Weaver はグリーンフィールドの Symfony 7 以上プロジェクトや、明示的で予測可能な SQL とワーカーセーフな永続化を求めて Doctrine から移行中のアプリケーションに最適です。