When accessing model attrs inside relation logic in laravel the attrs are all null when eager loading, if lazy loading it works fine.
Model relation :
public function organization()
{
return $this->belongsTo(Organization::class, 'organization_id');
}
public function currentOrder()
{
// Note that this will not work if eager loading the relation
// for some reason all model's attrs are null when eager loading
$subscription = $this->organization->currentAdhesionSubscription;
if ($subscription) {
return $this->morphOne(Order::class, 'parent')
->whereHas('ticketsWithPrice', fn($q) => $q->where('ticket_id', $subscription->ticket_id));
}
}
If lazy load the relation it works :
$model->load('currentOrder');
$model->currentOrder;
If eager loading it won’t work :
$model = Model::with('currentOrder')->first();
$model->currnetOrder // Error of accessing "currentAdhesionSubscription" on null which is organization which is a relation, but even when I access an attr of the model such as id it returns null when eager loading
Why model attrs are null when being accessed from whithin an eager loaded relation ?
2
Answers
When you do
Model::with('currentOrder')->first()
, you are not in the scope of a specific model instance, so$this
in your relation will be an empty instance of the model you are working with, essentially the same as if you donew Model()
.You should always think in database context when writing relations. So one thing you could do in your case is to manually join the needed tables. In your case, you have plenty of Models/tables involved, so it might also be a good idea to step back and re-think the database structure.
Modify
currentOrder
Logic for Eager LoadingUse eager loading to load
organization
separately and avoid accessing it inside the relation logic:using this approach, you’re essentially avoiding the need to access the
organization
relation insidecurrentOrder
.Another approach is to Manually Load
organization
BeforecurrentOrder
in Eager Loading by doing this:with the approach above, you’re ensuring that the
organization
relationship is eager loaded before resolving thecurrentOrder
relation.Another approach is to preload the
currentAdhesionSubscription
relation in the same query asorganization
to ensure it’s available whencurrentOrder
is resolveddoing this, ensures that when
currentOrder
is being resolved, the necessary data fromorganization
is already available.