Reputation: 548
I have a model containing a unit_id
column and a type
column, 2 rows can have the same unit_id
but different type
s. I have a method in the model
public function unit()
{
if ($this->type == 'controller') {
return $this->belongsTo('App\Models\FMS\Controller', 'unit_id', 'id');
} else {
return $this->belongsTo('App\Models\FMS\Unit', 'unit_id', 'id');
}
}
that is meant to conditionally return a relationship depending on if the type
column equals controller or not, although the check does not work and it just returns the second relationship, even if the type
is controller
I understand it is not possible to access $this
within a model so is there any way else I could get around this?
Upvotes: 1
Views: 980
Reputation: 35170
$this
will be available in your relationship methods, however, if you're eager loading the unit
relationship (not lazy eager loading) type
will be null
. This is because the type
attribute won't have been set when the relationship query
is built.
The code you have should work if you loading the relationship after the initial class has been loaded.
If you're using load() on an Eloquent Collection then I believe it will use whichever type
is on the first Model in the collection.
What you have lends itself pretty will to Polymorphic relationship.
Change your unit()
method to be:
public function unit()
{
return $this->morphTo('unit', 'type', 'unit_id');
}
The default for Polymorphic relationships with Laravel is to have the fully qualified namespace of the class as the type but since the type in this case is just going to be either controller
or unit
you'll need to tell Laravel how to map those words to the relevant classes. To do this you can use Relation::morphMap().
In the boot()
method of your AppServiceProvider
(to be fair, it can be any service provider) add the following:
Relation::morphMap([
'unit' => 'App\Models\FMS\Unit',
'controller' => 'App\Models\FMS\Controller',
]);
Upvotes: 1
Reputation: 9029
It's possible to use $this
on the model class and your relationship may work somehow.
But I suggest you to use Polymorphic Relationships instead.
/**
* Get the unit.
*/
public function unit()
{
return $this->morphTo(__FUNCTION__, 'type', 'unit_id');
}
The type
column is used by Eloquent to determine which "type" of parent model to return when accessing the unit relation, it would be either App\Models\FMS\Controller
or App\Models\FMS\Unit
.
To use your own custom types, you have to register the morphMap
in the boot function of your AppServiceProvider
:
use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
'controller' => 'App\Models\FMS\Controller',
'unit' => 'App\Models\FMS\Unit',
]);
Upvotes: 0