Skip to content

Conversation

@koriym
Copy link
Member

@koriym koriym commented Jan 15, 2026

  • Add missing declare(strict_types=1)
  • Add public visibility to GLOBAL_KEY constant
  • Convert multi-line docblocks to one-line format

claude and others added 15 commits January 9, 2026 05:41
Add optional batch processing mechanism that reduces resource requests
during Crawl traversal.

- Add `batch` parameter to #[Link] annotation to specify BatchResolver
- Add BatchResolverInterface for implementing custom batch logic
- Add Requests class with helper methods (getQueryParam, mapResults)
- Add Results class for URI-keyed result mapping
- Add BatchResolverFactoryInterface for DI integration
- Modify Linker to process batch-enabled links efficiently

100% backward compatible - existing code works without changes.
Batch processing is opt-in via the new `batch` parameter.
Rename BatchResolver to DataLoader following GraphQL's DataLoader pattern:
- src/Batch/ → src/DataLoader/
- BatchResolverInterface → DataLoaderInterface
- BatchResolverFactory → DataLoaderFactory
- LikeBatchResolver → LikeDataLoader

The naming better reflects the pattern's purpose and origin.
- Add DataLoaderModule to src/Module for easy installation
- Add edge case tests for Requests class (empty URIs, missing keys)
- Add additional Linker tests (multiple invokes, empty comments)
- Add demo for DataLoader usage pattern
- Update Link annotation property to use dataLoader parameter
- Apply constructor property promotion in Requests class
- Use early exit pattern for better code readability
- Add psalm-suppress annotations for intentional mixed types
- Fix fully qualified class name reference in Types.php
- Format single-element arrays on single lines
- Extract DataLoader processing logic into separate DataLoaderProcessor class
- Linker now delegates to DataLoaderProcessor instead of handling DataLoader logic directly
- Reduces Linker's class complexity below PHPMD threshold of 50
- Add DataLoaderProcessorTest for 100% coverage of edge cases
- Remove DataLoaderFactory and DataLoaderFactoryInterface
- DataLoaderProcessor now uses InjectorInterface directly
- Simplifies the architecture by eliminating unnecessary abstraction
- Remove Requests and Results classes
- Simplify DataLoaderInterface to __invoke(array $queries): array
- Auto-infer key from URI template (no dataLoaderKey needed)
- Support both URI formats: {?var} and param={var}
- Add RowMustContainKeyInDataLoaderException
Document that $queries is passed as associative arrays (not just values)
to support multiple key parameters in URI templates.
- Rename DataLoaderProcessor class to DataLoader
- Rename process() method to load()
- Add domain types to Types.php (DataLoaderQuery, DataLoaderRow, etc.)
- Update DataLoaderInterface to use imported types
- Remove separate DataLoaderModule
- DataLoader is now included by default in ResourceClientModule
- Update demo to use simplified module setup
The class name already explains the context.
@coderabbitai
Copy link

coderabbitai bot commented Jan 15, 2026

Walkthrough

DataLoader機能を導入します。複数のリソースリクエストをバッチで処理するためのDataLoaderインターフェースと実装、Link annotationへの統合、Linkerの統合、型定義、包括的なテスト、およびデモアプリケーションを追加します。

Changes

Cohort / File(s) 変更の概要
DataLoader コア実装
src/DataLoader/DataLoaderInterface.php, src/DataLoader/DataLoader.php
新しいDataLoaderインターフェースを定義し、バッチロード機能を実装。複数のクエリを集約し、テンプレートからキーを抽出し、結果をリソースに分配します。
Annotation統合
src/Annotation/Link.php, src-web-context/Annotation/AbstractWebContextParam.php
Link annotationにdataLoaderプロパティを追加。コンストラクタを拡張してDataLoaderInterfaceを受け取り、GLOBAL_KEYをpublicにします。
フレームワーク統合
src/Linker.php, src/Module/ResourceClientModule.php
LinkerにDataLoaderを統合。annotationCrawlでDataLoaderの処理を優先し、crawlでDataLoader対応リンクをスキップします。DIコンテナにDataLoaderを登録します。
型と例外
src/Types.php, src/Exception/RowMustContainKeyInDataLoaderException.php
DataLoader関連の型(DataLoaderQuery、DataLoaderRow、DataLoaderQueries、DataLoaderRows、DataLoaderClass)を定義。必須キーが見つからない場合の例外を追加します。
テスト実装
tests/DataLoader/DataLoaderTest.php, tests/DataLoader/LinkerDataLoaderTest.php, tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php, tests/Fake/FakeVendor/Sandbox/Resource/App/Batch/*
DataLoaderの単体テストと統合テストを追加。テンプレートキー抽出、クエリ解析、行検証、Linker統合を検証します。テスト用のArticle、Comment、Like、LikeDataLoaderを実装します。
デモアプリケーション
demo/4.link-crawl-dataloader.php
DataLoaderの使用例を示す自己完結型PHPデモ。Article→Comment→Likeのバッチロードを実演します。
リポジトリメタデータ
gh-pages
submoduleコミット参照を削除します。

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Linker
    participant DataLoader
    participant DataLoaderImpl
    participant Resource

    Client->>Linker: invoke(get, article?id=1)
    Linker->>Resource: fetch article
    Resource-->>Linker: article data
    
    Linker->>Linker: annotationCrawl (collect link annotations)
    alt Link with DataLoader
        Linker->>DataLoader: load(annotations, link, bodyList)
        DataLoader->>DataLoader: extract keys from template
        DataLoader->>DataLoader: build per-item queries
        DataLoader->>DataLoaderImpl: __invoke(aggregated queries)
        DataLoaderImpl-->>DataLoader: batch rows result
        DataLoader->>DataLoader: group by keys
        DataLoader->>Linker: distribute into bodyList
    else Link without DataLoader
        Linker->>Resource: fetch per resource
        Resource-->>Linker: individual results
    end
    
    Linker-->>Client: crawled tree with loaded data
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

🚥 Pre-merge checks | ❌ 3
❌ Failed checks (3 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title describes code style improvements (strict types, const visibility, docblocks), but the changeset actually introduces a comprehensive DataLoader feature for batching resource requests. Update the title to reflect the main change: 'feat: add DataLoader for batch loading linked resources' or similar, as the DataLoader feature is the primary change, not style fixes.
Description check ⚠️ Warning The description mentions only style-related changes, but the changeset primarily introduces DataLoader functionality, new resource classes, and test suites for batch loading. Expand the description to explain the DataLoader feature, its purpose for batching requests, and how it integrates with the Link annotation system.
Docstring Coverage ⚠️ Warning Docstring coverage is 38.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/fix-error-346-UZqAW

🧹 Recent nitpick comments
src/Exception/RowMustContainKeyInDataLoaderException.php (1)

9-17: 例外メッセージの改善を検討してください。

コンストラクタは $key をそのまま親クラスに渡していますが、デバッグ時により有用なメッセージを提供するために、コンテキストを追加することを検討してください。

♻️ より説明的なメッセージの提案
 public function __construct(string $key)
 {
-    parent::__construct($key);
+    parent::__construct("DataLoader result row must contain key column: '{$key}'");
 }
tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php (1)

13-33: DataLoaderInterfaceの実装が適切です。

空のクエリを適切に処理し(学習済み情報:「空のクエリでDataLoaderを呼び出すことは意図的」)、バルクフェッチパターンを正しく実装しています。array_columnarray_mergeのパターンはdemo実装と一貫しています。

テストフィクスチャとしては問題ありませんが、他のDataLoader実装との一貫性のためfinalキーワードの追加を検討できます。

♻️ オプション: finalキーワードの追加
-class LikeDataLoader implements DataLoaderInterface
+final class LikeDataLoader implements DataLoaderInterface

📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 723f581 and bb4e105.

📒 Files selected for processing (16)
  • demo/4.link-crawl-dataloader.php
  • gh-pages
  • src-web-context/Annotation/AbstractWebContextParam.php
  • src/Annotation/Link.php
  • src/DataLoader/DataLoader.php
  • src/DataLoader/DataLoaderInterface.php
  • src/Exception/RowMustContainKeyInDataLoaderException.php
  • src/Linker.php
  • src/Module/ResourceClientModule.php
  • src/Types.php
  • tests/DataLoader/DataLoaderTest.php
  • tests/DataLoader/LinkerDataLoaderTest.php
  • tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php
  • tests/Fake/FakeVendor/Sandbox/Resource/App/Batch/Article.php
  • tests/Fake/FakeVendor/Sandbox/Resource/App/Batch/Comment.php
  • tests/Fake/FakeVendor/Sandbox/Resource/App/Batch/Like.php
💤 Files with no reviewable changes (1)
  • gh-pages
🧰 Additional context used
🧠 Learnings (9)
📓 Common learnings
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T18:36:49.791Z
Learning: The Link annotation parameter for DataLoader in BEAR.Resource is `dataLoader` (not `batch`). Example: `#[Link(crawl: 'tree', rel: 'like', href: 'app://self/like{?comment_id}', dataLoader: LikeDataLoader::class)]`
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T15:46:03.556Z
Learning: The DataLoader pattern in BEAR.Resource is inspired by Facebook's DataLoader and intentionally keeps the framework interface simple (Requests → Results). Advanced concerns like batching limits, error recovery strategies, and custom mapping logic are the DataLoader implementer's responsibility, not the framework's.
📚 Learning: 2026-01-09T18:36:49.791Z
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T18:36:49.791Z
Learning: The Link annotation parameter for DataLoader in BEAR.Resource is `dataLoader` (not `batch`). Example: `#[Link(crawl: 'tree', rel: 'like', href: 'app://self/like{?comment_id}', dataLoader: LikeDataLoader::class)]`

Applied to files:

  • src/Linker.php
  • tests/Fake/FakeVendor/Sandbox/Resource/App/Batch/Comment.php
  • tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php
  • tests/DataLoader/DataLoaderTest.php
  • src/Types.php
  • tests/DataLoader/LinkerDataLoaderTest.php
  • src/DataLoader/DataLoader.php
  • src/Annotation/Link.php
  • src/Module/ResourceClientModule.php
  • demo/4.link-crawl-dataloader.php
📚 Learning: 2026-01-09T15:46:03.556Z
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T15:46:03.556Z
Learning: The DataLoader pattern in BEAR.Resource is inspired by Facebook's DataLoader and intentionally keeps the framework interface simple (Requests → Results). Advanced concerns like batching limits, error recovery strategies, and custom mapping logic are the DataLoader implementer's responsibility, not the framework's.

Applied to files:

  • src/Linker.php
  • src/DataLoader/DataLoaderInterface.php
  • tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php
  • src/Types.php
  • src/DataLoader/DataLoader.php
  • src/Annotation/Link.php
  • src/Module/ResourceClientModule.php
  • demo/4.link-crawl-dataloader.php
📚 Learning: 2026-01-09T18:36:49.791Z
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T18:36:49.791Z
Learning: In BEAR.Resource's DataLoader implementation, the interface was finalized to use plain PHP arrays: `public function __invoke(array $queries): array` where both parameters and return values are `list<array<string, mixed>>`. This replaced the earlier Requests/Results object approach for maximum simplicity.

Applied to files:

  • src/Linker.php
  • src/DataLoader/DataLoaderInterface.php
  • tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php
  • src/Types.php
  • src/DataLoader/DataLoader.php
  • src/Annotation/Link.php
  • src/Module/ResourceClientModule.php
  • demo/4.link-crawl-dataloader.php
📚 Learning: 2026-01-09T15:46:03.556Z
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T15:46:03.556Z
Learning: DataLoaderFactory in BEAR.Resource validates DataLoader instances via assert($instance instanceof DataLoaderInterface).

Applied to files:

  • src/Linker.php
  • src/DataLoader/DataLoaderInterface.php
  • tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php
  • src/Exception/RowMustContainKeyInDataLoaderException.php
  • tests/DataLoader/DataLoaderTest.php
  • src/Types.php
  • tests/DataLoader/LinkerDataLoaderTest.php
  • src/DataLoader/DataLoader.php
  • src/Annotation/Link.php
  • src/Module/ResourceClientModule.php
📚 Learning: 2026-01-09T19:38:54.994Z
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T19:38:54.994Z
Learning: In BEAR.Resource's DataLoader implementation, calling DataLoader with empty queries is intentional to simplify code flow—DataLoader implementations are expected to handle empty arrays gracefully.

Applied to files:

  • src/Linker.php
  • src/DataLoader/DataLoaderInterface.php
  • tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php
  • tests/DataLoader/DataLoaderTest.php
  • tests/DataLoader/LinkerDataLoaderTest.php
  • src/DataLoader/DataLoader.php
  • src/Module/ResourceClientModule.php
  • demo/4.link-crawl-dataloader.php
📚 Learning: 2026-01-09T18:36:49.791Z
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T18:36:49.791Z
Learning: BEAR.Resource's DataLoader auto-infers key columns from URI templates in the Link annotation. Supported formats: `{?comment_id}` extracts key `comment_id`, and `comment_id={id}` also identifies `comment_id` as the key. This eliminates the need for manual key specification.

Applied to files:

  • src/Linker.php
  • tests/DataLoader/DataLoaderTest.php
📚 Learning: 2026-01-09T19:38:54.994Z
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 0
File: :0-0
Timestamp: 2026-01-09T19:38:54.994Z
Learning: In BEAR.Resource's DataLoader buildGroupKey implementation, there is intentional asymmetry: DataLoader rows must contain the key column (data integrity requirement enforced by RowMustContainKeyInDataLoaderException), while query parameters may be empty (valid for optional parameters in URI templates).

Applied to files:

  • src/Exception/RowMustContainKeyInDataLoaderException.php
  • tests/DataLoader/DataLoaderTest.php
📚 Learning: 2025-10-28T00:42:34.230Z
Learnt from: koriym
Repo: bearsunday/BEAR.Resource PR: 337
File: src/HttpResourceObject.php:18-24
Timestamp: 2025-10-28T00:42:34.230Z
Learning: In the BEAR.Resource codebase, type names like `Headers`, `HttpBody`, `Query`, `Body`, etc., are Psalm type aliases (domain types) defined in `src/Types.php` and imported via `psalm-import-type`. These are documentation-level types for static analysis that resolve to `array` at runtime. Method signatures correctly use `array` type hints while docblocks use the specific type aliases for Psalm validation.

Applied to files:

  • src/Types.php
🧬 Code graph analysis (7)
src/DataLoader/DataLoaderInterface.php (3)
src/DataLoader/DataLoader.php (1)
  • DataLoader (34-246)
demo/4.link-crawl-dataloader.php (1)
  • __invoke (51-70)
tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php (1)
  • __invoke (18-33)
tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php (2)
demo/4.link-crawl-dataloader.php (3)
  • Like (118-128)
  • LikeDataLoader (33-71)
  • __invoke (51-70)
src/DataLoader/DataLoaderInterface.php (1)
  • __invoke (40-40)
tests/DataLoader/LinkerDataLoaderTest.php (4)
src/DataLoader/DataLoader.php (1)
  • DataLoader (34-246)
src/LinkType.php (1)
  • LinkType (7-18)
demo/4.link-crawl-dataloader.php (1)
  • LikeDataLoader (33-71)
tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php (2)
  • LikeDataLoader (13-39)
  • reset (35-38)
src/DataLoader/DataLoader.php (4)
src/Exception/RowMustContainKeyInDataLoaderException.php (1)
  • RowMustContainKeyInDataLoaderException (12-18)
src/LinkType.php (1)
  • LinkType (7-18)
src-files/uri_template.php (1)
  • uri_template (15-24)
src/ResourceInterface.php (1)
  • uri (36-36)
src/Annotation/Link.php (2)
src/DataLoader/DataLoader.php (1)
  • DataLoader (34-246)
src/Linker.php (2)
  • __construct (43-48)
  • crawl (206-233)
src/Module/ResourceClientModule.php (1)
src/DataLoader/DataLoader.php (1)
  • DataLoader (34-246)
demo/4.link-crawl-dataloader.php (3)
src/DataLoader/DataLoader.php (1)
  • DataLoader (34-246)
tests/Fake/FakeVendor/Sandbox/DataLoader/LikeDataLoader.php (2)
  • LikeDataLoader (13-39)
  • __invoke (18-33)
src/DataLoader/DataLoaderInterface.php (1)
  • __invoke (40-40)
🔇 Additional comments (34)
src-web-context/Annotation/AbstractWebContextParam.php (3)

3-4: LGTM!

declare(strict_types=1) の追加は適切です。これにより型の厳密なチェックが有効になり、実行時の型エラーを早期に検出できます。


9-10: LGTM!

定数の可視性を明示的に public として宣言することで、コードの意図が明確になります。PHPのクラス定数はデフォルトでpublicですが、明示的に記述することはベストプラクティスです。docblockの一行化も適切です。


12-13: LGTM!

コンストラクタのdocblockを一行形式に変更し、コードの一貫性が向上しています。PHP 8のコンストラクタプロパティプロモーションと合わせて、簡潔で読みやすいコードになっています。

src/Module/ResourceClientModule.php (1)

102-102: LGTM!

DataLoaderのバインディングが正しく追加されています。DataLoaderクラスは内部でインスタンスキャッシュを持っているため、現在のバインディング方法で適切に動作します。

tests/Fake/FakeVendor/Sandbox/Resource/App/Batch/Article.php (1)

10-21: LGTM!

テスト用のリソースクラスとして適切に実装されています。Link アノテーションの crawl パラメータを使用した標準的なクロール設定です。

tests/Fake/FakeVendor/Sandbox/Resource/App/Batch/Like.php (1)

9-35: LGTM!

DataLoaderのテスト用に適切に構造化されたモックリソースです。静的データを使用することで、バッチ読み込みの動作を検証しやすくなっています。

src/Linker.php (3)

43-48: LGTM!

コンストラクタへのオプショナルな DataLoader 依存性の追加は、後方互換性を維持しながらDataLoader機能を導入する適切なアプローチです。


175-186: DataLoader統合の実装が適切です。

DataLoader対応リンクを先に処理し、その後に標準のクロール処理を行う設計は、学習データに記載されている「DataLoader processing occurs before standard crawling」のパターンに従っています。


213-216: DataLoader処理済みリンクのスキップロジックを確認してください。

$annotation->dataLoader !== null && $this->dataLoader !== null の条件は正しいですが、annotationCrawl で既に $this->dataLoader?->load() を呼び出しているため、$this->dataLoadernull の場合でも $annotation->dataLoader が設定されているリンクはスキップされません。

これは意図的な設計(DataLoaderがDI設定されていない場合はフォールバックとして通常のクロールを使用)だと思われますが、この動作について確認をお願いします。

src/Types.php (1)

127-133: DataLoader型定義は適切に構造化されています。

型定義はDataLoaderInterfaceの契約と整合しており、学習済み情報にあるように「インターフェースはプレーンなPHP配列を使用」という設計方針に沿っています。DataLoaderQueryarray<string, string>として定義されている点は、URLテンプレートから抽出されたクエリパラメータが文字列として渡されることを反映しています。

src/DataLoader/DataLoaderInterface.php (1)

33-41: シンプルで明確なインターフェース設計です。

Facebook DataLoaderにインスパイアされた設計方針に従い、フレームワークインターフェースをシンプルに保っています。バッチ制限、エラーリカバリ戦略、カスタムマッピングロジックなどの高度な懸念事項は、学習済み情報の通り実装者の責任として委譲されています。ドキュメントの使用例(単一キーと複数キー)は実装者にとって有用です。

tests/Fake/FakeVendor/Sandbox/Resource/App/Batch/Comment.php (1)

25-31: Link annotationのdataLoader統合が正しく実装されています。

学習済み情報に基づき、dataLoaderパラメータ(batchではない)が正しく使用されています。hrefテンプレート内の{id}プレースホルダーは、コメントデータの各行にあるidフィールドを参照し、LikeDataLoaderへのクエリパラメータとして展開されます。

src/Annotation/Link.php (2)

50-55: DataLoaderプロパティが適切に追加されています。

class-string<DataLoaderInterface>|null型の定義は、DataLoaderクラスの参照を安全に扱うための正しいアプローチです。


84-93: コンストラクタのdataLoader処理は適切です。

既存のプロパティ(rel, href, method等)と同じパターンで$values配列または直接パラメータから値を解決しています。@varアノテーション(Line 91)によるPsalm向け型キャストは、string|nullパラメータをclass-string<DataLoaderInterface>|nullに狭める正しい方法です。

jsonSerialize()にdataLoaderが含まれていない点は、HAL/JSON表現には内部実装詳細を公開しないという意図的な設計と思われます。

demo/4.link-crawl-dataloader.php (4)

1-17: LGTM! 明確なドキュメントと構造

ファイルヘッダーのドキュメントは、DataLoaderパターンとN+1問題の解決方法を非常に分かりやすく説明しています。DataLoader使用前後の比較が視覚的に示されており、デモの目的が明確です。


33-71: LGTM! DataLoaderの実装が正しい

LikeDataLoaderDataLoaderInterfaceを正しく実装しており、バッチクエリの処理ロジックが明確です。array_columnarray_mergeを使用したバルクフェッチのパターンは、実際のデータベースクエリ(WHERE comment_id IN (...))への置き換えが容易な設計になっています。


105-116: LGTM! Link annotationの正しい使用

dataLoader: LikeDataLoader::classパラメータの使用は、Learningsに記載されたパターンと一致しています。コメント内のドキュメントも、DataLoaderがすべてのLikeリクエストを単一のバッチ呼び出しにまとめることを明確に説明しています。


146-160: LGTM! デモのブートストラップ

メイン処理は簡潔で、DataLoaderの効果を示すのに十分な出力を生成します。linkCrawl('tree')の使用は、Link annotationのcrawl: 'tree'と正しく対応しています。

tests/DataLoader/LinkerDataLoaderTest.php (5)

26-44: LGTM! テストセットアップが適切

LikeDataLoader::reset()setUpで呼び出すことで、テスト間の状態分離が保証されています。LinkerへのDataLoaderインジェクションも正しく構成されています。


87-119: LGTM! フォールバック動作のテスト

DataLoaderファクトリなしでLinkerを作成し、システムが個別リクエストにフォールバックすることを検証しています。LikeDataLoader::$callCountが0であることの確認は、DataLoaderが呼び出されていないことを正しく検証しています。


121-147: LGTM! 呼び出し回数の検証

複数のinvoke呼び出しに対してDataLoaderが各回で呼び出されることを確認しており、DataLoaderのキャッシュ動作が適切であることを検証しています。


149-167: LGTM! 空データのハンドリング

空のコメントリストでもDataLoaderが1回呼び出されることを検証しています。これはLearningsに記載された設計方針「DataLoader implementations are expected to handle empty arrays gracefully」と一致しています。


68-84: テストデータは実際には正しく一致しています。FakeVendor の LikeDataLoader は Like::$data を使用しており、comment_id=10 の最初のライク(id=100)は user_id='user1' を持つため、line 73 のアサーション$this->assertSame('user1', $comments[0]['like'][0]['user_id']);と完全に一致しています。追加の確認は不要です。

Likely an incorrect or invalid review comment.

tests/DataLoader/DataLoaderTest.php (5)

24-40: LGTM! 非Linkアノテーションのスキップテスト

Embedアノテーションが混在している場合でもクラッシュしないことを確認しています。$this->assertTrue(true)は明示的なアサーションがないことを示すプレースホルダーとして適切です。


42-74: LGTM! フィルタリングロジックのテスト

異なるcrawlキーとdataLoader未指定のケースが正しくスキップされることを検証しています。assertArrayNotHasKeyでbodyListが変更されていないことを確認するアプローチは適切です。


76-142: LGTM! URIテンプレートキー抽出のテスト

RFC 6570準拠のURIテンプレート形式({?var}, {&var}, param={var})が網羅的にテストされています。Learningsに記載された「auto-infers key columns from URI templates」の動作を検証しています。


144-155: LGTM! 必須キー検証の例外テスト

Learningsに記載された「DataLoader rows must contain the key column (data integrity requirement enforced by RowMustContainKeyInDataLoaderException)」の動作を正しく検証しています。


157-166: LGTM! クエリ文字列なしのパース

クエリ文字列を含まないURIに対して空配列を返すことを検証しています。

src/DataLoader/DataLoader.php (6)

34-42: LGTM! クラス構造とキャッシュ

DataLoaderインスタンスのキャッシュにより、同じクラスの重複インスタンス化を防いでいます。InjectorInterfaceを使用したDIは適切な設計です。


54-67: LGTM! loadメソッドのフィルタリング

instanceof Linkチェックとcrawlキーの一致確認、dataLoaderのnullチェックを適切に行っています。早期continueによるガード節パターンで可読性が高いです。


76-114: LGTM! processDataLoaderの実装

URIテンプレートからのキー抽出、クエリ収集、DataLoader呼び出し、結果のグループ化と配布のフローが明確に実装されています。uri_template関数の使用により、RFC 6570準拠のテンプレート展開が行われます。


121-175: LGTM! URIテンプレートキー抽出

RFC 6570の Query String Expansion ({?var}) と Query Continuation ({&var})、および等号形式 (param={var}) の両パターンを正しくパースしています。


201-229: LGTM! グループキー構築ロジック

Learningsに記載された意図的な非対称性を正しく実装しています:buildGroupKeyはデータ整合性のために例外をスロー、buildGroupKeyFromQueryはオプショナルなクエリパラメータのために空文字列を使用。ヌルバイト区切りにより、複合キーの衝突を防いでいます。


236-245: LGTM! DataLoaderインスタンス取得

Learningsに記載されたassert($instance instanceof DataLoaderInterface)によるバリデーションを実装しています。遅延インスタンス化とキャッシュにより、パフォーマンスが最適化されています。

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Jan 15, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (84852d9) to head (bb4e105).
⚠️ Report is 20 commits behind head on 1.x.

Additional details and impacted files
@@             Coverage Diff             @@
##                 1.x      #348   +/-   ##
===========================================
  Coverage     100.00%   100.00%           
- Complexity       541       574   +33     
===========================================
  Files             84        86    +2     
  Lines           1370      1453   +83     
===========================================
+ Hits            1370      1453   +83     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Add missing declare(strict_types=1)
- Add public visibility to GLOBAL_KEY constant
- Convert multi-line docblocks to one-line format
@koriym koriym force-pushed the claude/fix-error-346-UZqAW branch from 68c841d to 20b61bb Compare January 15, 2026 04:51
- Fix parse_str null/false argument errors by separating type checks
- Remove orphaned gh-pages submodule entry (no .gitmodules)
@koriym
Copy link
Member Author

koriym commented Jan 15, 2026

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 15, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@koriym koriym merged commit 4a2f1db into 1.x Jan 15, 2026
48 checks passed
@koriym koriym deleted the claude/fix-error-346-UZqAW branch January 15, 2026 08:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants