Following Laravel docs (and Laravel attach pivot to table with multiple values) I'm unable to see the attached values without calling fresh()
on the top-level model. Is there a better way to attach these models?
I don't want to refresh the entire model because other relationships are already loaded. Doing so would cause re-querying, instantiating, and overhead.
$productsToSync = $productsCollection->mapWithKeys(fn ($subscriptionProduct) => [
$subscriptionProduct->id => [
'quantity' => $subscriptionProduct->quantity,
'amount' => $subscriptionProduct->amount,
'item_id' => $subscriptionProduct->item_id,
]
])->toArray();
$subscription->products()->attach($productsToSync);
// This exception passes and is NOT thrown --> SubscriptionProducts are in the DB
throw_unless(
SubscriptionProducts::whereSubscriptionId($subscription->id)->count() > 0,
new \Exception("No SubscriptionProducts in DB?!)
);
// required NOT to throw ... but it refreshes and subsequently requires re-querying
// any already loaded relationships
// $subscription = $subscription->fresh();
throw_if(
$subscription->products->isEmpty(),
new \Exception("Products not attached to subscription WTF!?!")
);
class Subscription extends Model {
public function products(): BelongsToMany
{
return $this->belongsToMany(Products::class, 'subscription_products', 'subscription_id', 'product_id')
->using(SubscriptionProduct::class)
->as('subscriptionProducts')
->withPivot('id', 'item_id', 'quantity', 'amount');
}
}
You can reload a specific relationship with load
instead of refreshing the entire model.
$subscription->products()->attach($productsToSync);
// this will mutate $subscription
// no need to do $subscription = $subscription->...
$subscription->load('products');
throw_if(
$subscription->products->isEmpty(),
new \Exception("Products not attached to subscription WTF!?!")
);