user12789707
user12789707

Reputation:

Laravel | Return rows in order based off pivot

I have the following setup:

stages:

| id | name | order |

commands:

| id | name   | body         |
------------------------------=
| 1  | test   | phpunit      |
| 2  | style  | echo "style" |
| 3  | deploy | deploy       |

command_stage:

| command_id | stage_id | order |
---------------------------------
| 1          | 1        | 1     |
| 2          | 2        | 1     |
| 3          | 1        | 2     |

Basically, I would like to create a method on the stage model which allows me to get all of the commands back based off of the order, but commands have a specific order and so do the stages.

So each command is stored under a stage so we know which part to run but each command also has an order in that stage. Now I know I can do something like the following:

$inOrder = collect();

Stage::get()->each(function ($stage) {
    $commands = $stage->commands()->orderByPivot('order')->get();

    $inOrder->push($commands);
});

return $inOrder;

But I was wondering if there is a nicer way to do this? Or even a way to do this solely on one database hit?

Upvotes: 0

Views: 29

Answers (1)

Tim Lewis
Tim Lewis

Reputation: 29268

Pre-load and sort the relationship:

$stages = Stage::with(['commands' => function ($subQuery) { 
  $subQuery->orderBy('command_stage', 'order');
}])->get();

foreach($stages as $stage) {
  $inOrder->push($stage->commands);
}

This method of Eager-Loading will reduce the N+1 query issue of doing $stage->commands() inside the foreach() loop.

Upvotes: 1

Related Questions