Weave 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

Bonus Laravel Relations Laravel Package

thybag/bonus-laravel-relations

Extends Laravel's Eloquent ORM with bonus relationship types beyond the built-in hasOne, hasMany, and belongsTo helpers, making it easy to define richer model associations and reuse common relation patterns without writing custom query code.

View on GitHub
Deep Wiki
Context7

Getting Started

thybag/bonus-laravel-relations is a small utility package that adds extra Eloquent relationship types on top of Laravel's built-ins. Treat it as a modelling convenience, not a framework: there is no admin UI, no config to publish, and typically no service provider to register — you pull in a trait per model and get new relation methods.

Minimum steps:

  1. composer require thybag/bonus-laravel-relations
  2. Check the constraint that resolved. 0.6.0 is the Laravel 13-compatible line; if you are still on Laravel 11/12, Composer should keep you on 0.5.x, but pin explicitly in composer.json so a future composer update on a mixed-version monorepo does not surprise you.
  3. Open the README's relation table first — it is the authoritative list of what is actually shipped, and it is short. Then skim src/ to see the trait names, since that is what you will use in your models.
  4. First real use case: you have a reporting screen that needs "all X for this Y" across two hops, and today you are hand-writing ->join() chains in a controller. Replace that with the package's relation method, then ->with() it and delete the join.

Implementation Patterns

Trait-per-model, declared like any other relation. The package's traits expose relation methods that return standard Relation instances. That is the important property: because they return Relation, everything downstream — with(), withCount(), whereHas(), load(), loadMissing() — behaves as you already expect. Do not build a parallel abstraction around them.

Compose, don't replace. Keep the natural hasMany/belongsTo chain on the model and add the bonus relation alongside it as a named convenience:

class Team extends Model
{
    use HasBonusRelations; // trait name per README

    public function owner(): BelongsTo { ... }

    public function activeMembers(): /* bonus relation */
    {
        return $this->bonusRelation(...)->where('active', true);
    }
}

Scoping inside the relation method is usually better than scoping at every call site — it keeps withCount('activeMembers') honest across the app.

Eager-load deliberately. Use these relations with with() for list endpoints, and withCount() when the UI just shows a badge. Because the underlying SQL is a join or exists subquery rather than N queries, eager loading is where the package actually pays for itself; using it lazily gives you the worst of both worlds.

Tests are the spec. These relations are easy to get subtly wrong (wrong key, wrong intermediate model). Write a feature test per relation asserting a known fixture set, plus one assertDatabaseCount-style check against a hand-written query builder version of the same result. When you upgrade the package, that test is your regression net.

Verify generated SQL at least once. In a tinker session or a test, dump ->toSql() for each bonus relation you adopt and paste the query into your DB client. Five minutes here catches almost every surprise (duplicate rows from a missing distinct, unexpected whereNull, extra joins from global scopes).

Gotchas and Tips

Version pinning is the real story of 0.6.0. The only change is Laravel 13 support. That is good news — the package is maintained — but it also means the Laravel constraint widened, so re-run your suite after upgrading rather than assuming relation internals are untouched.

Key and table inference is the usual failure point. Bonus relations have more "guesses" to make than a plain hasMany (foreign key, owner key, intermediate model, sometimes a pivot). If a relation returns empty unexpectedly, pass the keys explicitly before you start debugging anywhere else.

Inverse relations are not automatic. Laravel cannot infer the inverse of a non-standard relation. Provide your own belongsTo back-reference and note it in the model docblock.

Global scopes and soft deletes propagate through intermediate models. A SoftDeletes model in the middle of the chain will change your result set, and withTrashed() on the endpoint will not necessarily reach it. Assert both directions in a test.

whereHas on these relations compiles to correlated subqueries. Fine for a filter on a page of 50; a problem in an export over 500k rows. For big reports, fall back to a query-builder join and keep the relation for the UI path.

Duplicates in joins. Multi-hop joins can multiply rows when the intermediate table has several matches. If you see the same model twice in a collection, that is a signal to add distinct or rethink the relation — do not paper over it with ->unique() in the controller.

Debugging recipe: DB::listen() in a local service provider, log slow queries over ~50ms, and confirm your eager loads are actually batching. If a page issues one query per row, you forgot with() somewhere — Model::preventLazyLoading() in non-production is the cheapest guard.

Extension points are thin by design. There is no config file to hook into. If you need different behaviour, subclass or copy the relation class into app/ — the package is small enough that forking a single trait is a legitimate option and cheaper than fighting an abstraction.

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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo