Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

phayes0289's avatar

How to display related records inside of a foreach loop of users

This is my index method that displays a list of users who signed up to work overtime for given shift id. It also displays the number of hours the user has previous worked through $subquery.

public function index(Request $request)
    {
        // Set the current date with the specific times
        $currentDateTime = Carbon::parse(now());

        // Calculate the last October 1
        $lastOctober = Carbon::now()->month >= 10 ? Carbon::create(null, 10, 1) : Carbon::create(null, 10, 1)->subYear();

        // Check if 'shiftid' is not in the request and set default value
        if (!$request->has('shiftId')) {
            $request['shiftId'] = OvertimeShift::where('start_dt', '<=', $currentDateTime)
                ->where('end_dt', '>=', $currentDateTime)
                ->first()->id;
        }

        // Get the shiftid from the request
        $shift = OvertimeShift::where('id', $request['shiftId'])
            ->first();

        $shifts = OvertimeShift::all();
        
        $subquery = OvertimeSignup::leftJoin('overtime', 'overtime_signups.user_id', '=', 'overtime.user_id')
            ->select('overtime_signups.user_id', DB::raw('SUM(CASE WHEN overtime.shift_id < ' . $shift->id . ' THEN overtime.duration ELSE 0 END) as total_duration'))
            ->where('overtime_signups.shift_id', $shift->id)
            ->where(function ($query) use ($lastOctober) {
                $query->where('overtime.created_at', '>=', $lastOctober)
                    ->orWhereNull('overtime.created_at');
            })
            ->groupBy('overtime_signups.user_id');

        $signups = OvertimeSignup::with(['user.currentAssignment', 'createdBy.currentAssignment', 'user.personnelPhones'])
            ->joinSub($subquery, 'total_durations', function ($join) {
                $join->on('overtime_signups.user_id', '=', 'total_durations.user_id');
            })
            ->select('overtime_signups.*', 'total_durations.total_duration')
            ->orderBy('total_durations.total_duration', 'asc')
            ->where('overtime_signups.shift_id', $shift->id)
            ->get();

        return view('stamfordct::overtime/hitlists/index', compact('signups', 'shift', 'shifts', 'assignments'));
        
    }

This is the blade code for outputting the list of users:

  <table id="dt-basic-example" class="table table-bordered table-hover table-striped w-100">
            <thead>
            <tr>
                <th>Index</th>
                <th>Member</th>
                <th>Shift</th>
                <th>Station</th>
                <th>Phone Numbers</th>
                <th>Notes</th>
                <th>Assignments</th>
                <th>Hours</th>
                <th></th>
            </tr>
            </thead>
            <tbody>
            @foreach ($signups as $index => $signup)

                <tr>
                    <td>{{$index+1}}</td>
                    <td>{{$signup->user->currentAssignment->rank->code}} {{$signup->user->lastname}}
                        , {{$signup->user->firstname}}
                        <span class="d-block"><small>Created By: {{$signup->createdBy->firstname}} {{$signup->createdBy->lastname}} @ {{ $signup->created_at }} </small></span>
                    </td>
                    <td>{{$signup->user->currentAssignment->shift->code}}</td>
                    <td>{{$signup->user->currentAssignment->station->code}}</td>
                    <td> @foreach ($signup->user->personnelPhones as $phone)
                            <a href="tel:{{ $phone->phone_number }}"
                               class="mt-1 d-block fs-sm fw-400 text-dark">
                                <i class="fas fa-mobile-alt text-muted mr-2"></i> {{ $phone->phone_number }}
                            </a>
                        @endforeach</td>

                    <td>@if($signup->notes)
                            {{ $signup->notes }} only
                        @endif
                    </td>
                    <td>
                        {{--  Display Assignments Here for todays shift--}}
                    </td>
                    <td>
                        {{ $signup->total_duration }}
                    </td>

                    <td>
                        <a href="{{ route('sfd.overtime.hitlist.create', [$shift->id, $signup->id]) }}"
                           class="btn btn-primary btn-sm">Log OT</a>

                    </td>
                </tr>
            @endforeach
            </tbody>
            <tfoot>
            <tr>
                <th>Index</th>
                <th>Member</th>
                <th>Shift</th>
                <th>Station</th>
                <th>Phone Numbers</th>

                <th>Notes</th>
                <th>Assignments</th>
                <th>Hours</th>
                <th></th>
            </tr>
            </tfoot>
        </table>

What I need to do is display any “Overtime” model entries for today's shift_id in the seventh column of the table using a foreach loop. There may be none, or there may be numerous records to display. The following eloquent query will get me all of those records, but I have no idea on how I can either include them with the query or otherwise. Also, it needs to display only the records for each user on their own line of data.

$assignments = Overtime::where('shift_id', $shift->id)->get();

How would I do such a thing? Is this done through relationships?

0 likes
2 replies
LaryAI's avatar
Level 58

To display the "Overtime" model entries for today's shift_id in the seventh column of the table, you can indeed use relationships to make this process more efficient and clean. Here’s how you can achieve this:

  1. Define the Relationship in the User Model: First, ensure that you have a relationship defined in your User model to fetch the related Overtime entries.

    // In User.php model
    public function overtimes()
    {
        return $this->hasMany(Overtime::class);
    }
    
  2. Modify the Query to Eager Load the Overtime Entries: Update your index method to eager load the overtimes relationship for the users.

    public function index(Request $request)
    {
        // Set the current date with the specific times
        $currentDateTime = Carbon::parse(now());
    
        // Calculate the last October 1
        $lastOctober = Carbon::now()->month >= 10 ? Carbon::create(null, 10, 1) : Carbon::create(null, 10, 1)->subYear();
    
        // Check if 'shiftid' is not in the request and set default value
        if (!$request->has('shiftId')) {
            $request['shiftId'] = OvertimeShift::where('start_dt', '<=', $currentDateTime)
                ->where('end_dt', '>=', $currentDateTime)
                ->first()->id;
        }
    
        // Get the shiftid from the request
        $shift = OvertimeShift::where('id', $request['shiftId'])->first();
    
        $shifts = OvertimeShift::all();
    
        $subquery = OvertimeSignup::leftJoin('overtime', 'overtime_signups.user_id', '=', 'overtime.user_id')
            ->select('overtime_signups.user_id', DB::raw('SUM(CASE WHEN overtime.shift_id < ' . $shift->id . ' THEN overtime.duration ELSE 0 END) as total_duration'))
            ->where('overtime_signups.shift_id', $shift->id)
            ->where(function ($query) use ($lastOctober) {
                $query->where('overtime.created_at', '>=', $lastOctober)
                    ->orWhereNull('overtime.created_at');
            })
            ->groupBy('overtime_signups.user_id');
    
        $signups = OvertimeSignup::with(['user.currentAssignment', 'createdBy.currentAssignment', 'user.personnelPhones', 'user.overtimes' => function ($query) use ($shift) {
                $query->where('shift_id', $shift->id);
            }])
            ->joinSub($subquery, 'total_durations', function ($join) {
                $join->on('overtime_signups.user_id', '=', 'total_durations.user_id');
            })
            ->select('overtime_signups.*', 'total_durations.total_duration')
            ->orderBy('total_durations.total_duration', 'asc')
            ->where('overtime_signups.shift_id', $shift->id)
            ->get();
    
        return view('stamfordct::overtime/hitlists/index', compact('signups', 'shift', 'shifts', 'assignments'));
    }
    
  3. Update the Blade Template to Display the Overtime Entries: Modify your Blade template to loop through the overtimes relationship and display the entries in the seventh column.

    <table id="dt-basic-example" class="table table-bordered table-hover table-striped w-100">
        <thead>
        <tr>
            <th>Index</th>
            <th>Member</th>
            <th>Shift</th>
            <th>Station</th>
            <th>Phone Numbers</th>
            <th>Notes</th>
            <th>Assignments</th>
            <th>Hours</th>
            <th></th>
        </tr>
        </thead>
        <tbody>
        @foreach ($signups as $index => $signup)
            <tr>
                <td>{{ $index + 1 }}</td>
                <td>{{ $signup->user->currentAssignment->rank->code }} {{ $signup->user->lastname }}, {{ $signup->user->firstname }}
                    <span class="d-block"><small>Created By: {{ $signup->createdBy->firstname }} {{ $signup->createdBy->lastname }} @ {{ $signup->created_at }} </small></span>
                </td>
                <td>{{ $signup->user->currentAssignment->shift->code }}</td>
                <td>{{ $signup->user->currentAssignment->station->code }}</td>
                <td>
                    @foreach ($signup->user->personnelPhones as $phone)
                        <a href="tel:{{ $phone->phone_number }}" class="mt-1 d-block fs-sm fw-400 text-dark">
                            <i class="fas fa-mobile-alt text-muted mr-2"></i> {{ $phone->phone_number }}
                        </a>
                    @endforeach
                </td>
                <td>
                    @if($signup->notes)
                        {{ $signup->notes }}
                    @endif
                </td>
                <td>
                    @foreach ($signup->user->overtimes as $overtime)
                        <div>{{ $overtime->description }} ({{ $overtime->duration }} hours)</div>
                    @endforeach
                </td>
                <td>{{ $signup->total_duration }}</td>
                <td>
                    <a href="{{ route('sfd.overtime.hitlist.create', [$shift->id, $signup->id]) }}" class="btn btn-primary btn-sm">Log OT</a>
                </td>
            </tr>
        @endforeach
        </tbody>
        <tfoot>
        <tr>
            <th>Index</th>
            <th>Member</th>
            <th>Shift</th>
            <th>Station</th>
            <th>Phone Numbers</th>
            <th>Notes</th>
            <th>Assignments</th>
            <th>Hours</th>
            <th></th>
        </tr>
        </tfoot>
    </table>
    

By following these steps, you will be able to display the related Overtime entries for each user in the seventh column of your table. This approach leverages Eloquent relationships to keep your code clean and efficient.

Please or to participate in this conversation.