Skip to content

Only resolve model method relations once - #270

Open
bennothommo wants to merge 1 commit into
developfrom
fix/repeated-model-relation-reflection
Open

bennothommo wants to merge 1 commit into
developfrom
fix/repeated-model-relation-reflection

Conversation

@bennothommo

@bennothommo bennothommo commented Oct 26, 2026 •

Copy link
Copy Markdown
Member

Instead of repeating reflection on the model class each time a relation is checked, this does one pass on the first model relation call, and caches the result.

Dynamic methods are still checked live each time.

This also resolves a bug where an initial hasRelation call would cache a single relation and cause other relation methods (such as getDefinedRelations) to only return the single relation.

Thanks to @JonasPardon for initial idea for fix.

Summary by CodeRabbit

  • Bug Fixes
    • Improved relation discovery so dynamically added relations are recognized only on the model instance where they were added.
    • Relation methods remain discoverable after looking up another relation on the same model.

Instead of repeating reflection on the model class each time a relation
is checked, this does one pass on the first model relation call, and
caches the result.

Dynamic methods are still checked live each time.

Resolves wintercms/winter#1581
Replaces #268

Thanks to @JonasPardon for initial fix.
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1738523b-87fe-461e-abf9-85b33d9fded3
Commits

Reviewing files that changed from the base of the PR and between 7b506f5 and 3477095.

Files selected for processing: 2
  • src/Database/Concerns/HasRelationships.php
  • tests/Database/Concerns/HasRelationshipsTest.php

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

Relation discovery now caches class-declared methods identified as relations through a Relation attribute or registered relation return type. It checks extension and dynamic methods on each discovery call. Relation checks and definition lookups use the updated flow, and definition caching applies only to methods in the class-level cache. Tests cover discovery after a relation lookup and dynamic relation methods.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Severity of issue fixed: Medium

Possibly related issues

Merge Risk: Minimal · up to 34770

No actionable merge-blocking issue remains; normal test checks are appropriate before merging.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 12 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main change: cache model relation-method discovery after the initial resolution while handling dynamic methods separately.
Linked Issues check Passed The PR meets the coding requirements in issue #1581. getClassRelationMethods() performs one reflection scan per model class and stores the result, including an empty result. hasRelation() now uses…
Out of Scope Changes check Passed The changes stay within issue #1581. The source changes replace relation-method discovery and caching behavior. The tests cover the changed discovery and dynamic-method behavior. No unrelated product …
Full details: Linked Issues check

Explanation

The PR meets the coding requirements in issue #1581. getClassRelationMethods() performs one reflection scan per model class and stores the result, including an empty result. hasRelation() now uses the cached path. getRelationMethods() checks extension and dynamic methods on every call. The added tests verify that one relation lookup does not limit later relation discovery and that dynamic relation methods are not cached across instances.

Full details: Out of Scope Changes check

Explanation

The changes stay within issue #1581. The source changes replace relation-method discovery and caching behavior. The tests cover the changed discovery and dynamic-method behavior. No unrelated product behavior or unrelated files are changed.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@austinderrick austinderrick left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! Thank you for this!
I've been implementing something like this with a hacky override in my deployments. :)

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.

Performance: getRelationMethods() runs a full class reflection scan on every relation/attribute access

3 participants