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:
JavaScript
x
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.
JavaScript
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
JavaScript
class MyModel extends Model {
use HasDynamicRelation;
}
Now you can use the following method to add new relationships
JavaScript
MyModel::addDynamicRelation('some_relation', function(MyModel $model) {
return $model->hasMany(SomeRelatedModel::class);
});