Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Inverse Relations Laravel Package

stayallive/laravel-inverse-relations

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require stayallive/laravel-inverse-relations
    

    Publish the config (if needed):

    php artisan vendor:publish --provider="Stayallive\InverseRelations\InverseRelationsServiceProvider"
    
  2. Define an Inverse Relation: Add HasInverseRelation trait to your model and define the inverse relation in the $inverseRelations property.

    use Stayallive\InverseRelations\HasInverseRelation;
    
    class Post extends Model
    {
        use HasInverseRelation;
    
        protected $inverseRelations = [
            'comments' => ['Comment', 'post'], // [relation_name, [related_model, inverse_relation]]
        ];
    
        public function comments()
        {
            return $this->hasMany(Comment::class);
        }
    }
    
  3. First Use Case: Fetch a Post with its comments and automatically hydrate the inverse relation (post) on each Comment:

    $post = Post::with('comments')->find(1);
    // $post->comments now have their `post` relation populated automatically
    

Implementation Patterns

Workflows

  1. Circular Relationships: Avoid N+1 queries when fetching models with inverse relations:

    // Without inverse relations (N+1 risk):
    $comments = Comment::where('post_id', 1)->get();
    foreach ($comments as $comment) {
        $comment->post; // N+1 query
    }
    
    // With inverse relations (single query):
    $post = Post::with('comments')->find(1);
    // All comments' `post` relations are hydrated in one go
    
  2. MorphMany Support: Define inverse relations for polymorphic relationships:

    class Comment extends Model
    {
        use HasInverseRelation;
    
        protected $inverseRelations = [
            'commentable' => ['Commentable', 'comments'],
        ];
    
        public function commentable()
        {
            return $this->morphTo();
        }
    }
    
    class Post extends Model
    {
        public function comments()
        {
            return $this->morphMany(Comment::class, 'commentable');
        }
    }
    
  3. Conditional Inverse Relations: Use closures to conditionally define inverse relations:

    protected $inverseRelations = [
        'tags' => function () {
            return ['Tag', 'taggable'];
        },
    ];
    

Integration Tips

  • Eager Loading: Always eager-load inverse relations when possible to avoid runtime hydration:

    $posts = Post::with(['comments', 'comments.post'])->get();
    
  • Customizing Hydration: Override the hydrateInverseRelations method in your model to customize behavior:

    protected function hydrateInverseRelations()
    {
        $this->loadMissing(['post']); // Custom logic
    }
    
  • Performance: Disable inverse relations for read-heavy models where hydration isn’t needed:

    protected $inverseRelations = [];
    

Gotchas and Tips

Pitfalls

  1. Circular Dependencies: Avoid defining inverse relations that create infinite loops (e.g., A has B, B has A with inverse pointing back to A). This can cause stack overflows or excessive queries.

  2. Model Not Found: If the inverse relation’s parent model doesn’t exist, the relation will be null. Handle this gracefully:

    $comment->post ?? throw new ModelNotFoundException();
    
  3. Polymorphic Conflicts: Ensure polymorphic relations (morphTo, morphMany) have consistent inverse definitions across all related models.

  4. Caching Issues: Inverse relations bypass Laravel’s query cache. If you rely on caching, manually cache the results:

    $comments = Cache::remember("post.$post->id.comments", now()->addHours(1), function () use ($post) {
        return $post->comments;
    });
    

Debugging

  • Enable Query Logging: Check for unexpected queries when hydrating inverse relations:

    DB::enableQueryLog();
    $post = Post::with('comments')->find(1);
    dd(DB::getQueryLog());
    
  • Verify Relation Definitions: Ensure $inverseRelations matches the actual relation names in your models. Typos will cause silent failures.

Config Quirks

  • Global Configuration: The package respects Laravel’s default query behavior (e.g., DB::select won’t trigger inverse hydration). Use Eloquent models for inverse relations to work.

  • Extension Points: Override Stayallive\InverseRelations\InverseRelationsServiceProvider to customize the package’s behavior globally.

Tips

  1. Useful for APIs: Inverse relations reduce payload size by avoiding redundant data in responses:

    return Post::with('comments')->find(1); // Comments include `post_id` implicitly
    
  2. Testing: Mock inverse relations in tests to avoid real database queries:

    $comment = new Comment();
    $comment->setRelation('post', new Post());
    
  3. Documentation: Clearly document inverse relations in your model’s PHPDoc to help other developers:

    /**
     * @property-read Post $post The parent post (inverse of comments).
     */
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai