phpgraph について
phpgraph は PHP プロジェクトを静的解析し、コーディングエージェント向けのコードナレッジグラフを構築します。呼び出し、ルート、メッセージ、依存関係、アーキテクチャを確度付きの事実として示し、コードを実行せず、マシン外へ送信しません。
主な機能
- 01型推論によるコールグラフの構築
- 02ルート、メッセージ、ハンドラーの対応付け
- 03依存関係と変更影響の追跡
- 04アーキテクチャ層とルールの確認
- 05API スキーマと実装の関連付け
- 06未解決の関係と解析上の不足を報告
活用シーン
- 01不慣れな PHP プロジェクトの把握
- 02ルートからハンドラーまでのリクエスト追跡
- 03変更前に影響箇所とテストを特定
- 04CI でアーキテクチャ層のルールを確認
MCP 対応
プロジェクト概要、グラフ検索、コード構造、ノード関係、影響分析、経路検索などのツールを通じて静的解析結果を MCP で提供します。グラフは初回利用時に構築され、コード変更時に差分更新されます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
docker run -i --rm ghcr.io/hbenabdallah/phpgraph:1.6.1ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ghcr.io/hbenabdallah/phpgraph:1.6.1stdioツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
phpgraph
AI コーディングエージェント向けの、PHP コードベースのナレッジグラフです。
MCP 経由の静的解析を、Sherpa、Claude Code、Codex、Cursor、その他すべての MCP クライアントに提供します。
LLM もネットワーク接続も埋め込みも不要です。各事実には信頼度が付与され、結果は決定的です。
英語 · フランス語
phpgraph を使う理由
見慣れない PHP プロジェクトに置かれた AI エージェントは、ファイルを一つずつ読み、名前を grep します。しかし、実際のコードベースで最も重要な点を見落とします。何が何を呼び出すのか、どのハンドラーがメッセージを受け取るのか、どのコントローラーがルートを処理するのか、メソッドを変更したら何が壊れるのか、どのレイヤーがどのレイヤーに依存しているのかです。
phpgraph は nikic/php-parser を使ってプロジェクト全体を一度解析し、グラフからこうした質問に答えます。
- 推測ではなく、決定的な事実です。 すべての関係は、
EXTRACTED(コードから読み取ったもの)、INFERRED(宣言された型から解決したもの)、またはAMBIGUOUS(推測であることを明示したもの)に分類されます。 - わからないことも明示します。 解決できない呼び出し、存在しない
vendor/、ハンドラーのないメッセージなどの不足情報を報告するため、エージェントはコードを自分で読むべきタイミングがわかります。 - まず DDD とヘキサゴナルアーキテクチャ向けに、次にマイクロサービス向けに、そして PHP 全般向けに設計されています。 Symfony、Laravel、Ecotone、PrestaShop、WordPress、またはプレーンな PHP に対応します。
- プライバシーを前提に設計されています。 コードがマシンの外に出ることはなく、phpgraph がコードを実行することもありません。解析のみを行います。
機能
- 型推論に対応したコールグラフ:戻り値の型、連鎖呼び出し(
$a->b()->c())、ローカル変数、DocBlock(@return、@var)、vendor/の依存関係のシグネチャに対応しているため、Doctrine、Symfony、Laravel の API をたどれます。 - アーキテクチャ:DDD とヘキサゴナルアーキテクチャのレイヤー、境界づけられたコンテキスト、CI でチェックされるレイヤールール(
phpgraph check)、影響分析(impact_of)に対応しています。クラスやメソッドに依存しているものや、実行すべきテストを確認できます。 - メッセージとイベント:Symfony Messenger、Laravel のジョブとイベント、Ecotone、PrestaShop CQRS、WordPress のフック、ドメインイベント、独自のバスについて、属性、サービス設定(YAML、XML、PHP)、またはコードの形式から、送信元 → メッセージ → ハンドラーを追跡します。
- HTTP:ルート(Symfony の属性、YAML および PHP のルーティングファイル、API Platform のリソース、Laravel のルートファイル、コンテナのサービス ID を名前に持つコントローラー)をコントローラーに関連付け、HTTP 呼び出しを呼び出し先のルートに関連付けます。コントローラークラスがプロジェクトにも
vendor/にも存在しないルートは、ルーティングファイルとともに報告されます。 - 依存性注入:コンストラクターの型以外に Symfony コンテナ設定が注入するもの、タグに属するすべてのサービス(
tagged_iterator、#[AutowireIterator])、または ID で指定されたサービスを、PHP、YAML、XML の設定から特定します。リテラル引数を使って呼び出されるヘルパー(Wiring::wire($services, 'sales', ...)、評価されますが実行はされません)にも対応しています。たとえば、バリデーターは受け取るルールに関連付けられます。受け付けるものを宣言するルール(supports(object $input): bool { return $input instanceof CreateEstimateQuery; }。canHandle、acceptsなども対象です)は、別の入力を共有パイプラインに渡すユースケースから除外されます。入力のプロパティが保持するクラスも含まれます。インターフェース型の入力については、それを実装するプロジェクト内のクラスと、その入力が渡される先のパラメーター型も対象になります(QueryInterface $queryがsetUp(CreateEstimateQueryInterface $query)に渡される場合はCreateEstimateQuery)。読み取れないガードや、一部のクラスに対してのみ実行されるルールは保持され、supports() not resolvedとマークされます。 - マイクロサービス:サービスごとに個別の ID 空間を持ち、共有メッセージクラス、ルーティングキー、HTTP ルートを通じてサービス間のリンクを追跡します。
- API スキーマ:OpenAPI(Swagger)ドキュメントの操作を、それを実装するルートに関連付けます。別の API のドキュメントの場合は、そのクライアントの HTTP 呼び出しに関連付けます。protobuf サービスの RPC は、生成されたインターフェースを実装するクラスに関連付けます。ドキュメントに記載されているが実装されていないものや、どのドキュメントにも記載されていないルートを報告します。
impactは変更の背後にある操作(クライアントが依存するコントラクト)を一覧表示し、outlineは機能が対応する操作を一覧表示します。 - ゼロ設定の MCP サーバー:初回使用時に構築され、コードの変更時には差分のみを再構築します(8,400 ファイルのプロジェクトで編集あたり約 3 秒)。
クイックスタート
1. インストールします。 PHP は不要で、単一の実行ファイルです(x86_64 と ARM の Linux および macOS、x86_64 の Windows に対応):
curl -fsSL https://raw.githubusercontent.com/hbenabdallah/phpgraph/main/install.sh | sh # latest release
curl -fsSL https://raw.githubusercontent.com/hbenabdallah/phpgraph/main/install.sh | sh -s -- 0.2.0 # a given release
curl -fsSL https://raw.githubusercontent.com/hbenabdallah/phpgraph/main/install.sh | sh -s -- dev-main # the main branch
irm https://raw.githubusercontent.com/hbenabdallah/phpgraph/main/install.ps1 | iex # Windows
$env:PHPGRAPH_VERSION = "dev-main"; irm https://raw.githubusercontent.com/hbenabdallah/phpgraph/main/install.ps1 | iex
このスクリプトはバイナリをダウンロードし、SHA-256 を検証して、~/.local/bin に配置します(Windows の場合は %LOCALAPPDATA%\Programs\phpgraph に配置し、PATH に追加します)。PHPGRAPH_INSTALL_DIR を設定すると、配置先を変更できます。更新するには、もう一度実行してください。dev-main は main へのプッシュごとに再ビルドされます(edge のプレリリースです)。このバイナリは、static-php-cli でビルドされた、phpgraph を内蔵する静的 PHP ランタイムです。
PHP 8.2 以降がインストールされている場合、または Docker を使う場合:
composer require --dev hbenabdallah/phpgraph # or: composer global require hbenabdallah/phpgraph
curl -LO https://github.com/hbenabdallah/phpgraph/releases/latest/download/phpgraph.phar
docker pull ghcr.io/hbenabdallah/phpgraph # nothing else to install
2. エージェントを接続します。 mcp-config は、パスを埋め込んだすぐに貼り付けられる設定を出力します(Composer でインストールした場合は vendor/bin/phpgraph):
phpgraph mcp-config sherpa # Sherpa: a `sherpa mcp add` command, one declaration for every project
phpgraph mcp-config claude # Claude Code: a `claude mcp add` command, or .mcp.json
phpgraph mcp-config codex # Codex: ~/.codex/config.toml
phpgraph mcp-config cursor # Cursor: .cursor/mcp.json, shareable with the team
phpgraph mcp-config json # any other MCP client over stdio
phpgraph に接続していても、エージェントはまず grep を使いがちです。mcp-config は、プロジェクトの指示ファイル(CLAUDE.md、AGENTS.md)に追加する一文も出力します。これは、grep やファイルの読み取りより先に phpgraph を呼び出すようエージェントに指示するもので、サーバーの MCP 指示にも同じ内容が記載されています。
ターミナルのコーディングエージェントである Sherpa では、宣言を 1 つ追加するだけで、すべてのプロジェクトで使えます。Sherpa は、実行されているプロジェクトから MCP サーバーを起動します。
sherpa mcp add phpgraph -- ~/.local/bin/phpgraph serve
Sherpa のセッションでは、/mcp add でも同じことができ、ツールをすぐに利用できます。どちらの方法でも ~/.config/sherpa/mcp.json に書き込みます。
Claude Code の場合(mcp-config が出力する絶対パスを使用します):
claude mcp add phpgraph -- /home/you/.local/bin/phpgraph serve /path/to/project
3. エージェントに 「このプロジェクトの概要を教えてください」、「注文はどのように処理されますか?」、「OrderRepository::save を変更すると、何が壊れますか?」 のような質問をしてみましょう。最初の呼び出し時にグラフが構築され、その後は最新の状態に保たれます。
MCP ツール
| ツール | 用途 |
|---|---|
overview | まずはこちらを呼び出してください。Composer スタック、レイヤーを含む名前空間ツリー、境界づけられたコンテキスト、レイヤールール違反、メッセージ、HTTP ルート(各ルートのメソッド、パス、コントローラー、ファイルを最大30件まで表示し、それを超える場合はパスのプレフィックスごとにグループ化)、サービス、グラフでは確認できないことを示します。 |
query_graph | クラス名が分からない場合に、名前に含まれる単語からトピックに関連するコードを探します(Validator で検証されます)。名前が挙がったクラスの周辺にある機能のクラスも表示します。ルートに関する質問(「mooc courses routes」、「GET /courses」)では、一致するルートとそのコントローラーを返します。回答の周辺にあるクラス群はフォルダーごとに集計します(ContextRuleInterface: … 内に34件)。注入されるリストは一度だけ表示します(ContextValidator が34件の ContextRuleInterface を受け取る)。 |
outline | 機能を説明する前に、その構造の概要を確認します。自明でないロジックがある少数のファイルだけを読めば済むようにします。機能を構成するクラスを名前空間とレイヤーごとに示し、docblock の最初の文、パブリックシグネチャ、定数、列挙型のケースを表示します。周辺のインターフェースと基底クラス、およびモジュールごとの実装数(0件も表示)も示します。機能に至るルートを、実行されるクロージャーをたどってチェーンごとに表示します。本体を読んで分かる動作(条件付きの例外、早期リターン、定数による分岐、ループの上限、前後で比較される状態)を示します。サービス ID を含むコンテナーの設定、利用箇所、モジュールごとのテスト数、テストで確認されていない箇所、どこからも使われていないものも示します。約15 KBです。リストが途中で切れた場合は、すべての内容を含むセクション名(section behaviour、1~9 KB)が示されます。メソッド(OrderService::place)を指定すると、代わりにそのメソッドが実行する内容を示します。つまり、呼び出すメソッドを3段階先まで、それらのメソッドだけを含む各クラスとともに表示します。ハブ(20クラス以上から呼び出されるもの、シングルトンの getInstance())は集計しますが、追跡はしません。動作は最も近いものから表示します。 |
get_node | クラス、メソッド、ルート、チャネルを1つ指定し、関連情報をすべて確認します。それを使用するテストはモジュールごとに集計されます。 |
get_neighbors | あるノードを使用するもの(in)や、そのノードが依存するもの(out)を確認します。 |
impact_of | 変更前の影響を確認します。クラスまたはメソッドに依存するクラスをすべて、近い順に呼び出し箇所の行番号付きで示します。実装するインターフェースを通じた呼び出し元、書き込む状態に依存するコード、そこに至るルート(各チェーン付き)、テストヘルパーから特定した実行すべきテストも表示します。テストで確認されていないクラスや、アプリケーション内で使われていないクラスにも印を付けます。 |
shortest_path | 2つのコードがどのようにつながっているかを確認します。 |
god_nodes | コードの大部分が依存するハブを探します。 |
サーバーは、エージェントに最初に overview を呼び出すよう指示します。エージェントから見たパスの例(php-ddd-example):
Shortest path (4 hops):
PUT /courses/{id} --handled_by--> CoursesPutController::__invoke()
--dispatches--> CreateCourseCommand --handled_by--> CreateCourseCommandHandler::__invoke()
--calls--> CourseCreator::__invoke()
コマンドライン
phpgraph build [path] # phpgraph-out/graph.json and GRAPH_REPORT.md
phpgraph overview # stack, structure and gaps
phpgraph impact "OrderRepository::save" # what depends on it, and the tests to run (--all, --section tests, --format json)
phpgraph check # layer rules, for CI: exit code 1 on a new violation
phpgraph explain "PlaceOrderHandler" # a node and its relations (-d in|out)
phpgraph path "StockChecker" "DbalOrderRepository"
phpgraph query "how is stock checked"
phpgraph outline "notification validation" # the outline of a feature (--section flow, --format json)
phpgraph serve [path] # the MCP server, over stdio
phpgraph mcp-config claude|codex|cursor|json [--docker image]
build のオプション:パスを除外する -e(複数回指定可能)、依存関係を読み込まない --no-vendor、すべてのファイルを再度解析する --no-cache。vendor、node_modules、var、.git と、プロジェクト独自の .gitignore ファイルで無視されるファイルはスキップされます。プロジェクトより上位にある Git リポジトリのルールは適用されないため、無視対象のディレクトリにコピーされたプロジェクトも読み込まれます。ディレクトリに PHP ファイルが含まれていても、すべて除外されている場合は、build は失敗してその旨を示します。また、空のグラフを提供する代わりに、すべての MCP の回答の冒頭に警告が表示されます。デフォルトではメモリ制限はありません。PHPGRAPH_MEMORY_LIMIT=2G で上限を設定できます。PHP がインストールされている場合、opcache とその JIT によりビルドが約20%速くなります:php -d opcache.enable_cli=1 -d opcache.jit=tracing -d opcache.jit_buffer_size=128M vendor/bin/phpgraph build(Docker イメージと mcp-config が出力するコマンドでは、すでにこれらが使用されています)。
グラフに含まれる内容
| 関係 | From → to |
|---|---|
defines, imports | ファイル → クラス、use ステートメント |
extends, implements, uses_trait | クラス → 親クラス、インターフェース、トレイト |
has_method, overrides | クラス → メソッド、メソッド → オーバーライドするメソッド |
instantiates, references | new Foo();パラメーター、戻り値、プロパティの型、catch、instanceof、定数、属性 |
calls | メソッド → 解決されたメソッド。呼び出し箇所の行を含みます。メソッドが受け取ったクロージャーを実行する場合($apply(...))、そのメソッドはクロージャーが呼び出すものを呼び出します。INFERRED、via は closure of <the method writing it> |
dispatches, handled_by | 送信元 → メッセージまたはチャネル → ハンドラー;ルート → コントローラー;supports() メソッドでテストされるクラス → そのストラテジー |
contract | あるサービスから送信されたメッセージクラス → 別のサービスで処理される同じクラス |
requests | HTTP 呼び出し → 同じサービスまたは別のサービス内で到達するルート、あるいは別の API の OpenAPI ドキュメント内の操作 |
implemented_by | API スキーマ操作(operation:) → メソッドとパスを含むルート(OpenAPI)、または生成されたサービスを実装するクラスのメソッド(protobuf) |
receives | サービス → コンテナー設定によってそのサービスに注入される各サービス(タグ、ID、装飾されたサービス);via はその指定方法を示します。同じクラスの複数サービスのうちの 1 つの場合は service sales.pipeline |
reads_state_of | メソッド → コンストラクター以外で、そのメソッドが読み取るプロパティを変更する同じクラスのメソッド(hasErrors() → add())。INFERRED |
すべての関係には信頼度レベルがあります。
| レベル | 意味 |
|---|---|
EXTRACTED | 1 つのファイルのコード、または設定(属性、サービスタグ、ルートファイル)から読み取られています。 |
INFERRED | 宣言された型(パラメーター、プロパティ、$this、継承、戻り値の型、コードの構造)に基づいて、ファイル間で解決されています。 |
AMBIGUOUS | たとえば、型が不明なレシーバーで呼び出される、プロジェクト内で唯一同名のメソッドなど、推測に基づいています。 |
認識されるフレームワークと規約
| ハンドラーとリスナー | 送信されるメッセージ | HTTP | |
|---|---|---|---|
| Symfony | #[AsMessageHandler]、#[AsEventListener]、タグ messenger.message_handler と kernel.event_listener(YAML、XML、PHP、_instanceof)、getSubscribedEvents()、addListener() | MessageBusInterface、EventDispatcherInterface、名前付きイベント | #[Route](クラス定数内のパスも対象)、YAML および PHP のルーティングファイル、サービス ID で指定されたコントローラー;API Platform の #[ApiResource] と操作属性、およびそれらのプロバイダー、プロセッサー、コントローラーによる処理 |
| Laravel | $listen、Event::listen()、サブスクライバー(subscribe() 内の $events->listen()、または返されるマップ)、複数のイベントをまとめて受け取るリスナー(handle(Accepted|Rejected $event))、ジョブ(ShouldQueue、Dispatchable) | event()、dispatch()、ファサード、Job::dispatch() | Route::get/post/…、match、resource、view、redirect、prefix と domain を持つグループ、routes/api.php;baseUrl() を基準とする Http:: クライアント |
| Ecotone | #[CommandHandler]、#[EventHandler]、#[QueryHandler]、ルーティングキー | CommandBus、EventBus、DistributedBus、sendWithRouting() | |
| PrestaShop | #[AsCommandHandler]、#[AsQueryHandler] | CommandBusInterface::handle() | YAML ルーティング |
| WordPress | add_action()、add_filter() | do_action()、apply_filters() | |
| 独自コード | 名前で認識されるハンドラー属性とタグ、__invoke/handle(Message $m)、*Handler クラス | *Bus、*Dispatcher、*Publisher 型、集約の recordThat()、独自のバスラッパー | Guzzle、Symfony HttpClient、PSR-18 |
アーキテクチャ:レイヤー、境界づけられたコンテキスト、CI のルール
クラスのレイヤーは名前空間から読み取ります。最初に明示されたセグメント(`Domain`、`Application`、`Infrastructure`、`UI`、`Presentation`、`Port`、`Adapter`、`UseCase`)、または該当しない場合は最後の汎用セグメント(`Model`、`Entity`、`Controller`、`Http`、`Persistence`…)です。境界づけられたコンテキストはレイヤーの前(`CodelyTv\Mooc\Courses\Domain`)、またはプロジェクトでレイヤーを先に置く場合はレイヤーの後(`Core\Domain\Product`)から読み取ります。phpgraph check は、アプリケーションコードに階層化アーキテクチャのデフォルトルールを適用します。domain は application、infrastructure、interface に依存してはならず、application と port は infrastructure または interface に依存してはなりません。すでに違反があるプロジェクトでは、次のようになります。
phpgraph check --generate-baseline # accept today's violations in phpgraph-baseline.json
phpgraph check # fail on new ones only
マイクロサービス
独立した Composer アプリケーションを2つ以上含むリポジトリは、サービスに分割されます。モノレポのパッケージはプロジェクト内にとどまります。ルートがオートロードする、パスリポジトリとして宣言する、または replace するパッケージはサービスではなく、パーツです。サービスが必要とするライブラリ(パスリポジトリ、またはそのパッケージ名)は共通コードです。IDにはサービス名が付与されます(billing@App\Domain\Order)。また、名前が別のサービスの要素を解決することはありません。サービス間の連携にはコントラクトを使用します。
- あるサービスが送信し、別のサービスが処理する同じメッセージクラス:
contract; - ルーティングキー(
sendWithRouting('order.place', …)、#[CommandHandler('ticket.create')]、名前付きイベント):すべてのサービスで共有されるchannel:ノード; - 別のサービスのルートへの HTTP 呼び出し:
requests。パスが、他の HTTP メソッド専用に宣言されたルートと一致する呼び出しは報告されます。そのままでは失敗するためです; - API スキーマ:OpenAPI ドキュメントの
operation:ノード(GET /api/hotels/{hotel})、または protobuf サービスのoperation:ノード(CinemaService.Reserve)。それらを提供するルートまたはクラスがimplemented_byです。リポジトリのルートにあるドキュメントはすべてのサービス(API ゲートウェイ)を記述し、サービス内にあるドキュメントはそのサービスのみを記述します。
検出結果が適合しない場合は、任意の phpgraph.yaml でサービスを指定できます。
services:
- services/billing
- services/shipping
独自のルーティングファイル:XML のアクションコード
レガシーアプリケーションでは、画面から送信されるアクションコード(value="saveReservation")を使ってルーティングし、独自の XML ファイルでコントローラーメソッドに対応付けることがよくあります。phpgraph.yaml で形式を記述でき、形式はハードコードされていません。
actions:
- file: Framework/jacActions.xml
element: //action # XPath of the action elements
code: code # their attributes (these are the defaults)
controller: controller
method: method
controller_file: '{dir}/control/{name}CTRL.php' # _Stock/Reservation → _Stock/control/ReservationCTRL.php
target: target # the action or template it goes on to
forward: { element: forward, result: result, target: target }
cited_in: [html, js] # the screens quoting the codes
各アクションはルートノード(ACTION saveReservation)であり、そのメソッド(EXTRACTED)が handled_by で示されます。メソッドが継承されている場合は、コントローラーを参照します(via controller)。ターゲットとフォワードは、次のアクションまたはテンプレート(_Stock/SO_080/Resa.html は _Stock/views/SO_080/Resa.html を検索します)への references です。via は target または forward KO です。コード(value="saveReservation"、'saveReservation&id=')を引用する cited_in ファイルはアクションを参照し、状態は AMBIGUOUS です。impact_of には、そのルートに関連する画面が一覧表示されます。単語だけのコード(default、login)は検索されず、ミニファイされたファイルも対象外です。overview ではアクション数と、コントローラーまたはメソッドが見つからないアクションが一覧表示されます。メソッドの outline では、そのアクションからフローが始まります。query_graph("saveReservation routes") で検索できます。controller_class: '{name}CTRL' を指定すると、ファイルではなく名前でクラスを検索します。
仕組み
- 各 PHP ファイルを解析して、宣言、レシーバーの式の型を含む呼び出し、メッセージの送信とハンドラー、ルート、HTTP 呼び出しなどの事実を抽出します。
- ビルダーがそれらの事実をファイル間で解決します。継承や戻り値の型を通じて型を解決し、
vendor/のシグネチャは Composer のメタデータから必要に応じて読み込みます(解析のみで、実行はしません)。サービス定義はコンテナー設定から取得します。 - グラフは
phpgraph-out/graph.jsonに保存され、人が読める形式のGRAPH_REPORT.mdも生成されます。 再ビルドは差分のみを対象にします。ファイルの抽出結果は内容に基づいてキャッシュされ、どこにも宣言の変更がなければ、MCP サーバーは変更されたファイルの呼び出しだけを再解決します。結果はフルビルドと同一です。
実プロジェクトでの測定結果
phpgraph は、コミットに固定されたオープンソースプロジェクトのコーパスを対象に開発されており、すべての変更をその数値で評価しています(composer corpus:measure)。アプリケーションコードのみを対象としています。receiver typed は、phpgraph がレシーバーの型を判定できたメソッド呼び出しの割合です。
| プロジェクト | 種類 | PHP ファイル数 | ビルド | レシーバー型判定率 |
|---|---|---|---|---|
| php-ddd-example | DDD、CQRS | 304 | 0.4 s | 98.9 % |
| Sylius | Symfony eコマース | 4,946 | 6.5 s | 96.9 % |
| Akeneo PIM | ヘキサゴナル、境界づけられたコンテキスト | 8,416 | 10.3 s | 90.4 % |
| PrestaShop | CQRS とレガシーコード | 7,850 | 10.0 s | 96.1 % |
| Ecotone quickstart | 47 サービス、メッセージング | 583 | 0.6 s | 94.4 % |
| BookStack | Laravel | 1,513 | 2.8 s | 96.2 % |
| WordPress | フレームワークなし、フック | 1,899 | 5.3 s | 93.6 % |
さらに、4 つのマイクロサービスプロジェクトがコーパスを構成しています。RabbitMQ を介して連携する 2 つの Laravel サービスは、4 つのメッセージコントラクトで結ばれています。HTTP を介して連携する 4 つの Laravel サービスでは、phpgraph が GET のみを受け付けるルートに送信された POST を検出しました。Spiral のチケット予約システムでは、.proto ファイルで宣言された gRPC サービスを通じてサービス同士が呼び出しを行います。また、StayHub は、OpenAPI ファイルで記述された API ゲートウェイの背後に 7 つの Laravel サービスを配置しています。最後の 2 つのプロジェクトでは、API スキーマをコントラクトとして測定しています。StayHub のドキュメントにある 45 個すべての操作と、ticket-booking の 14 個すべての RPC が、それぞれの実装と結び付けられています。約 26,600 ファイルで解析エラーはゼロでした。メッセージ、ルート、サービスなど、プロジェクトごとの詳細は corpus/RESULTS.md をご覧ください。
エージェントとの使用
非公開の 4,800 ファイルの Symfony/DDD プロジェクトで測定しました。各構成で 3 回実行し、同じエージェント(Sherpa)を phpgraph 1.0.2 ありとなしで比較しました。
| 質問の種類 | phpgraph あり | 品質 |
|---|---|---|
影響範囲またはリファクタリング(impact_of) | トークン −42 %、時間 −50 %、ツール呼び出し −59 % | 同等以上 |
機能の説明(outline) | トークン −25 %、時間 −34 %、ツール呼び出し −49 %。デフォルトの outline ではトークン −31 % | 同等 |
phpgraph ありとなしの実行結果の範囲は重なりません。
他のコードグラフとの比較
Sylius(コーパスのコミット)、2026年10月時点、LLM なしでの比較です。同じマシン上の Docker で、phpgraph 1.0.2、codebase-memory-mcp 0.11.0、graphify 0.9.76(--code-only)を使用しました。呼び出しはサイトごと(ファイル、行、メソッド)に比較し、差分のサンプルをコードで確認しました。
| phpgraph | codebase-memory-mcp | graphify | |
|---|---|---|---|
| ビルド | 10 s | 17 s | 32 s |
| プロジェクトのメソッドにリンクされた呼び出しサイト | 22,870 | 32,274 | 4,005 |
| うち、型から解決されたもの | 22,747 | 4,314 | — |
OrderItemQuantityModifierInterface::modify() の呼び出し元を検出(コード内に17件) | 17件、誤検出なし | 11件、誤検出2件 | 0件、誤検出1件 |
| メッセージにリンクされた Messenger ハンドラー | 206 | 0 | 0 |
| コンテナーへの注入、ルート | 1,360、188 | 0、1(誤検出) | 0、0 |
- codebase-memory-mcp は、型から解決した呼び出しの99.7 %で phpgraph と一致します。残りのエッジはメソッド名から推測されています(信頼度0.04〜0.44)。両者が同じ呼び出しにリンクしている箇所では、9,400件のサイトで結果が異なり、追加された11,300件のエッジの大部分は、
vendor/内の呼び出しを同名のプロジェクトメソッドに関連付けたものです(確認した20件中19件)。 - graphify は
$this->other->foo()を現在のクラスのfoo()にリンクします。$this->foo()では正しいものの、確認した差分10件中10件で誤っていました。 - phpgraph にはなく、他のツールにある機能:他の言語、全文検索とベクトル検索、Cypher クエリ(codebase-memory-mcp)、インタラクティブな可視化とグラフ内のドキュメント(graphify)。
FAQ
phpgraph は私のコードをどこかに送信しますか? いいえ。ローカルで実行され、ネットワーク通信は行わず、LLM も使用しません。
コードを実行しますか? いいえ。PHP ファイルを解析し、JSON、YAML、XML の設定を読み取ります。autoload_classmap.php や PHP のサービスコンフィギュレーターも、読み込まずに解析します。
どの PHP バージョンを解析できますか? nikic/php-parser 5 で解析できるすべての構文です。PHP 7 と 8 の構文に加え、最新の文法では拒否されるファイルについては、削除済みの PHP 4 と 5 の構文($s{0}、=& new、08 のような8進数リテラル)も解析できます。phpgraph 自体には PHP 8.2 以降が必要です。
どのエージェントで使えますか? stdio 経由の MCP クライアントならどれでも使えます:Sherpa、Claude Code、Codex、Cursor、Claude Desktop などです。mcp-config は一般的なクライアント向けの設定を出力します。
どのくらいの規模のプロジェクトを処理できますか? コーパス内で最大のプロジェクトである Akeneo は8,400ファイルです。全体のビルドには約10 s、500 MB、編集後の再ビルドには約3 sかかります。
制限事項
- 読み取るのは PHP のみです。混在リポジトリの他の言語は
overviewに表示されますが、それらから PHP 部分への呼び出しはリンクされません。また、プロジェクトに PHP がまったく含まれていない場合は、MCP の指示にその旨が表示されます。 - グローバル関数への呼び出しはグラフのエッジになりませんが、関数の戻り値によって、その関数に続く呼び出しの型は決まります(
now()->addDay()、response()->json())。動的呼び出し($this->$name()、__call)は、クラスがドキュメント化しているメソッド(@method、@mixin)を通じてのみ解決されます。 - ジェネリクスは、プロジェクトと
vendor/の docblock(@template、@extends Repository<Order>、@return Collection<int, Item>、ScalarNodeDefinition<$this>)から読み取られます。テンプレートは、レシーバーの型と、それを引き継ぐ親クラスによって束縛されます。また、foreachは型付きコレクションの要素を順に処理します。ユニオン型(ドキュメント化されているか宣言されているResponse|ResponseFactory)は、メソッドを宣言しているメンバーに対して呼び出されます。メソッドを宣言しているメンバーがある場合に限ります。メソッドに渡されるクロージャには、そのメソッドが渡すとドキュメント化しているパラメーターが設定されます(@param callable($this): mixed、Laravel のwhen(fn ($query) => ...))。トレイトの使用にある@use HasFactory<HotelFactory>は、そのテンプレートを束縛します。メソッドのテンプレートは、各呼び出しの引数によって束縛されます。具体的には、引数が示すクラス(@param class-string<T>を持つgetRepository(Order::class))、値の型(@param T $value)、クロージャの戻り値(@param callable(): T、その戻り値の文やネイティブ型)です。@phpstan-returnと@psalm-returnは@returnより先に読み取られます。引数から判定できない条件(TAsync is false ? Response : PromiseInterface)は、各分岐のユニオン型になります。@propertyおよび@property-readでドキュメント化されたマジックプロパティは、その後のチェーンにも型を引き継ぎます。Eloquent モデルでは、キャスト('paid_at' => 'datetime'は Carbon、列挙型、キャストクラスのTGet)、タイムスタンプ、プロパティとして読み取られるリレーション($page->book、book()->getResults()の戻り値)も同様です。戻り値の型を宣言していないメソッドは、オーバーライド元のメソッドが宣言している戻り値(@inheritDoc)を返します。型に関する条件($id is array ? Collection : Model)は評価されず、mixedとドキュメント化されたファサードメソッド(DB::transaction())は不明のままです。 - マジックメソッドや、使用可能な戻り値の型がない依存関係に到達すると、チェーンはそこで止まります。PHP 組み込みのクラス(
DateTime、ArrayObject、SplObjectStorage、PDOなど)は、1 回生成されるシグネチャ(tools/internal-classes.php)から認識されますが、intlおよびmysqli拡張のクラスは認識されません。 vendor/がインストールされていない場合、呼び出しチェーンは最初の依存関係で止まります。- 実行時に構築されるサービス(コンパイラーパス、バンドル拡張、実行時にしか判明しない値から計算される ID)、XML ルート(ただし、
phpgraph.yamlでマッピングされたアクションファイルは除きます)、XML または YAML で宣言された API Platform リソース、OpenAPI と protobuf 以外の API スキーマ(GraphQL、AsyncAPI)は読み取られません。ゲートウェイによって書き換えられた OpenAPI パスは追跡されず、リンクできないインジェクションはoverviewに一覧表示されます。 - 同じ名前のメッセージクラスを宣言する 2 つのサービスは、同じクラスを共有しているものとして扱われます。
貢献
Issue とプルリクエストを歓迎します。CONTRIBUTING.md を参照してください。composer check が成功する必要があります(php-cs-fixer、PHPStan level max、PHPUnit)。分析に関する変更はコーパスに基づいて評価されます。PHP がインストールされていない場合は、bin/dev composer check ですべてを Docker 上で実行できます。
バージョンをまたいで安定しているもの(コマンド、MCP ツール、graph.json 形式)は docs/STABILITY.md に記載されています。変更点は変更履歴を参照してください。
リリースはバージョンタグをプッシュして公開します。リリースワークフローによって、PHAR、Linux、macOS、Windows 用の実行ファイル(tools/build-binary.sh)、Docker イメージ ghcr.io/hbenabdallah/phpgraph がビルドされます。
ライセンス
phpgraph は、PolyForm Shield License 1.0.0 に基づきソースコードを公開しています。phpgraph と競合しない目的であれば、企業内での利用を含め、使用、改変、再配布が可能です。このコードを使って競合製品を提供することは許可されていません。このライセンスは OSI 承認のオープンソースライセンスではありません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。