argonzalez's avatar

Use an existing collection to populate a relation

Say I have a collection of Representative::class and I have a collection of Sale::class which has a BelongsTo relationship pointing towards Representative::class.

Say earlier in the script I loaded a collection of Representative::class (maybe all of them) from the database.

Is there a way to use that collection to reference the relationships with Sale::class so I do not have to run another query to the database when I attempt to run Sale::with('representatives')->get().

I am trying to avoid multiple queries to the Representative table.

0 likes
2 replies
LaryAI's avatar
Level 58

Yes, you can use the setRelation method on the Sale model to set the relationship with the existing collection of Representative models. Here's an example:

// Assume we have loaded all Representative models into a $representatives collection
$representatives = Representative::all();

// Load all Sale models with the representatives relationship
$sales = Sale::with('representatives')->get();

// Loop through each Sale model and set the representatives relationship using the existing collection
$sales->each(function ($sale) use ($representatives) {
    $representative = $representatives->where('id', $sale->representative_id)->first();
    $sale->setRelation('representatives', $representative);
});

In this example, we first load all Representative models into a collection. Then, we load all Sale models with the representatives relationship using Sale::with('representatives')->get(). Finally, we loop through each Sale model and use the setRelation method to set the representatives relationship using the existing collection of Representative models.

Note that this approach assumes that the representative_id column on the Sale model matches the id column on the Representative model. If they have different names, you'll need to adjust the code accordingly.

argonzalez's avatar

@LaryAI This exact example still causes the representatives table to be queried twice.

Please or to participate in this conversation.