Laravel 5.4中关联模型并按Group的position字段排序的实现方法
Hey there! Let's work through this step by step. The main issues here are how your models are set up for the many-to-many relationship, and your current query isn't leveraging the pivot table correctly (plus it looks like your table structure might have a small mix-up with the position field).
Looking at your schema, you have position on the groups table—but that doesn't make sense if you want to sort leaders within a group by their unique position. That field should live on the group_leader pivot table instead, since each leader has a specific position per group. Your pivot table should look like this:
group_leader ------------- | id | group_id | leader_id | position | ------------
If you intended position to be a group-level field (unlikely for your use case), skip this step—but I’m guessing you meant leader position within the group.
Your current belongsToMany relationships need to include the pivot field (position) so we can use it for sorting. You can also optionally specify the custom pivot model if you need extra logic later:
// Leader.php class Leader extends Model { public function groups() { return $this->belongsToMany('App\Group') ->using('App\GroupLeader') // Optional, for custom pivot logic ->withPivot('position'); // Include the position field from the pivot table } } // Group.php class Group extends Model { public function leaders() { return $this->belongsToMany('App\Leader') ->using('App\GroupLeader') ->withPivot('position') ->orderBy('pivot_position', 'asc'); // Set default sorting here if you want } } // GroupLeader.php (only if you need custom pivot methods) class GroupLeader extends Pivot { // Add scopes or custom logic here, e.g., filtering active leaders }
Your original query tries to filter Leader by a group field that doesn't exist on the leaders table. Instead, fetch the Group first, then get its sorted leaders:
// Fetch group1 by its name (assuming your `groups` table has a `group` column for the name) $group1 = Group::where('group', 'group1_name')->firstOrFail(); // Get leaders sorted by position (uses the default order from the model) $group1Leaders = $group1->leaders; // Repeat for group2 $group2 = Group::where('group', 'group2_name')->firstOrFail(); $group2Leaders = $group2->leaders; return view('page.leadership')->with([ 'group1' => $group1Leaders, 'group2' => $group2Leaders, ]);
If you don’t want to set default sorting in the model, override it inline:
$group1Leaders = $group1->leaders()->orderBy('pivot_position', 'asc')->get();
In your Blade view, you can loop through each group’s leaders and access their details (including the position via the pivot):
<h2>Group 1 Leaders</h2> <ul> @foreach($group1 as $leader) <li> {{ $leader->first_name }} {{ $leader->last_name }} @if($leader->deceased) <em>(Deceased)</em> @endif <span class="position">Position: {{ $leader->pivot->position }}</span> </li> @endforeach </ul> <h2>Group 2 Leaders</h2> <ul> @foreach($group2 as $leader) <li> {{ $leader->first_name }} {{ $leader->last_name }} @if($leader->deceased) <em>(Deceased)</em> @endif <span class="position">Position: {{ $leader->pivot->position }}</span> </li> @endforeach </ul>
- Your pivot table name (
group_leader) already follows Laravel’s convention (singular model names in alphabetical order), so no extra configuration is needed there. - If you really intended
positionto stay on thegroupstable, the sorting logic would change—but that doesn’t align with sorting leaders within a group, so moving it to the pivot is the right call.
内容的提问来源于stack exchange,提问作者Dan

