Is it possible to set a model’s relationship dynamically? For example, I have model Page
, and I want to add relationship banners()
to it without actually changing its file? So does something like this exist:
Page::createRelationship('banners', function(){ $this->hasMany('banners'); });
Or something similar? As they are fetched using the magic methods anyway, perhaps I can add the relationship dynamically?
Thanks!
Advertisement
Answer
I’ve added a package for this i-rocky/eloquent-dynamic-relation
In case anyone still looking for a solution , here is one. If you think it’s a bad idea, let me know.
trait HasDynamicRelation { /** * Store the relations * * @var array */ private static $dynamic_relations = []; /** * Add a new relation * * @param $name * @param $closure */ public static function addDynamicRelation($name, $closure) { static::$dynamic_relations[$name] = $closure; } /** * Determine if a relation exists in dynamic relationships list * * @param $name * * @return bool */ public static function hasDynamicRelation($name) { return array_key_exists($name, static::$dynamic_relations); } /** * If the key exists in relations then * return call to relation or else * return the call to the parent * * @param $name * * @return mixed */ public function __get($name) { if (static::hasDynamicRelation($name)) { // check the cache first if ($this->relationLoaded($name)) { return $this->relations[$name]; } // load the relationship return $this->getRelationshipFromMethod($name); } return parent::__get($name); } /** * If the method exists in relations then * return the relation or else * return the call to the parent * * @param $name * @param $arguments * * @return mixed */ public function __call($name, $arguments) { if (static::hasDynamicRelation($name)) { return call_user_func(static::$dynamic_relations[$name], $this); } return parent::__call($name, $arguments); } }
Add this trait in your model as following
class MyModel extends Model { use HasDynamicRelation; }
Now you can use the following method to add new relationships
MyModel::addDynamicRelation('some_relation', function(MyModel $model) { return $model->hasMany(SomeRelatedModel::class); });