I have two models Product
and ProductType
which both have a relationship with the Usp
model. I have set up the models like this.
class Product extends Model
{
use HasFactory, SoftDeletes;
protected $guarded = [];
public function usps(): MorphToMany
{
return $this->morphToMany(Usp::class, 'uspable');
}
}
class ProductType extends Model
{
use HasFactory, SoftDeletes;
protected $guarded = [];
public function usps(): MorphToMany
{
return $this->morphToMany(Usp::class, 'uspable');
}
}
class Usp extends Model
{
use HasFactory, SoftDeletes;
protected $guarded = [];
public function products(): MorphToMany
{
return $this->morphedByMany(Product::class, 'uspable');
}
public function productTypes(): MorphToMany
{
return $this->morphedByMany(ProductType::class, 'uspable');
}
}
As far as I can see I have everything setup correctly but for some strange reason, when I call the property of the ProductType
model it returns null
(i.e. ProductType::find(1)->usps
). But when I call the Query Builder method ProductType::find(1)->usps()->get()
it gives me the correct results. For the Product model both ->usps
and ->usps()->get()
seem to work just fine. I have no idea what I am doing wrong here.
2
Answers
I fixed it by creating a trait called
HasUsps
and defining the builder method and custom attribute getter in it. and implemting the trait to every model that has a polymorphic relation with theUsp
model. It still feels like a workaround for something that should just work, but I have no idea where the 'real' problem lays. So for now this is fine.It looks like you have set up your relationships correctly, but there might be an issue with eager loading. By default, relationships are not loaded until you explicitly request them. When you use ->usps, it may not be eager loading the relationship, resulting in null. However, when you use ->usps()->get(), you are explicitly triggering the loading of the relationship.
To ensure that the relationship is loaded when you access it directly, you can use eager loading with the with method. Try modifying your code as follows:
By using with(‘usps’), you are instructing Laravel to eager load the "usps" relationship along with the "ProductType" model, and then you can access it directly without having to call ->usps()->get().
Alternatively, you can use the load method after retrieving the ProductType instance:
This should resolve the issue of returning null when accessing the usps relationship directly on the ProductType model.