Runtime Relation Mapping
HasDynamicRelations lets you register model relations at runtime.
It is ideal for reusable packages where consumers need project-specific relations without modifying package source code.
What Problem It Solves
In package-first architecture, package models should not hardcode every relation needed by every host project.
This trait allows relation injection from the app layer.
Basic Setup
use JobMetric\PackageCore\Models\HasDynamicRelations;
class Tag extends Model
{
use HasDynamicRelations;
}
Register Dynamic Relations
Tag::addDynamicRelation('posts', function ($model) {
return $model
? $model->morphedByMany(Post::class, 'taggable')
: (new Post)->morphedByMany(Tag::class, 'taggable');
});
Tag::addDynamicRelation('products', function ($model) {
return $model
? $model->morphedByMany(Product::class, 'taggable')
: (new Product)->morphedByMany(Tag::class, 'taggable');
});
Real project pattern (application layer):
Member::addDynamicRelation('orders', function ($model) {
return $model
? $model->morphedByMany(Order::class, 'memberable')
: (new Order)->morphedByMany(Member::class, 'memberable');
});
Usage
$tags = Tag::with(['posts', 'products'])->get();
Best Practices
- Register dynamic relations in model
boot()or a service provider - Use clear relation names (
orders,products, etc.) - Keep relation closures idempotent and deterministic
- Plan eager loading for heavy polymorphic relation graphs
Common Pitfalls
- Re-registering the same relation name unintentionally
- Registering dynamic relations from multiple scattered places
- Ignoring performance implications for polymorphic relations