Additional eloquent ORM relation types for laravel.
thybag/bonus-laravel-relations is a Laravel package for additional eloquent orm relation types for laravel..
It currently has 7 GitHub stars and 36.399 downloads on Packagist (latest version 0.6.0).
Install it with composer require thybag/bonus-laravel-relations.
Discover more Laravel packages by thybag
or browse all Laravel packages to compare alternatives.
Last updated
A selection of weird & wonderful additional relation types for laravel's eloquent ORM I've ended up needing.
Many of these are experimental and may behave in unexpected & none standard ways.
On the bright side - it's tested!
All licensed under the MIT license.
composer require thybag/bonus-laravel-relationsuse thybag\BonusLaravelRelations\Traits\BonusRelationsTrait; in to your model (or base model if you want them everywhere.)The relation traits can also be added individually if you prefer that.
composer testcomposer lintGet polymorphic relations of a single type.
public function shop()
{
return $this->belongsToMorph(Shop::class, 'noteable');
}
Define a relation via an unlimited number of middle tables.
public function products()
{
return $this->hasManyViaMany(Product::class)->via(Shop::class)->via(Franchise::class);
}
Get an aggregate result as a relation. The main benefit of this approach is it allows easy lazy loading of this data on collections + interaction with the results in a more eloquent like way.
public function productTotals()
{
return $this->hasAggregate(Product::class)->selectRaw('
COUNT(DISTINCT products.id) AS unique_products,
SUM(products.amount) * AVG(products.value) AS stock_value,
SUM(products.amount) AS total_products,
AVG(products.value) AS average_product_value
');
}
Additional transformations on data returned from hasAggregate can be defined by using withCallback(function($result){}) to define a transform function. Only one can be defined per relationship at present.
Use a local method as if it were a relation.
public function totalValue()
{
return $this->hasMethod(function () {
return ['total' => ($this->amount * $this->value)];
});
}
Define a one-to-one relation through a pivot table.
public function latestRating()
{
return $this->belongsToOne(Rating::class, 'shop_rating')->latest('created_at');
}
As the relationships HasMethod and HasAggregate don't return a traditional model from the database, a special model called type InertModel is used. This allows the relationship to fill the model with arbitrary attributes without the risk of causing unexpected behavior.
If you would like to use a custom InertModel rather than the one provided, create a config called bonus-laravel-relationships.php in your config folder, then set the value inertModel with the class path to the model you would like to use instead. I would recommend whatever model you use inherits from the base IntertModel to avoid unexpected behavior. Alternatively the hasMethod relationship supports a withModel or passing a model parameter to override this. Similar functionality is available in hasAggrgegate using the returnModel parameter.