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

SandraCarlsen's avatar

Sorting a foreach loop in blade with relationship data

Hello New laravel developer, coming from frontend and javascript so please dont kill me :-)

I have a problem with sorting a foreach loop in my blade I have this export to excel and everything is working as it should, I get the data to excel and it saves the file fine.

The problem is that I need to sort by the company name, data not in invoice table....

I have only user id in the invoice table, I want to sort by the name of the company that the user belongs to. that data is in the user table. I can get data from user table the normal way by $invoice->user->first_name

I have tried to do $invoices->user->sortBy(companies_title) as $invoice but that doesnt work.

The controller is only $invoices = Invoice::where('course_occasion_id', $courseOccasionId)->get();

is there a simple way to do this?

Best regards Sandra

0 likes
9 replies
fichby's avatar

@sandracarlsen you can create a function in your invoices model

public function userSorted {
    $this->user->orderBy('companies_title');
}

then you would call

$invoice->userSorted->first_name
ftiersch's avatar

Sorry @fichby but your solution doesn't make sense on multiple levels.

@sandracarlsen

You can give a callback function to the sortBy method so it will be sorted by the result of that function.

$invoices->sortBy(function ($invoice) {
    return $invoice->user->companies_title;
});
SandraCarlsen's avatar

thanks @fichby

This gets the data from user sorted.

But I needed the invoice to be sorted. Sorry for being vauge

the code

        @foreach($invoices as $invoice)
        
            <tr>
                <td>{{ $invoice->courseOccasion->course_occasion_id }}</td>
                <td>{{ $invoice->user->pnr }}</td>
        <td>{{ $invoice->user->first_name }}</td>
        <td>{{ $invoice->user->last_name }}</td>
                <td>{{ $invoice->price_excluding_vat }}</td>
        <td>{{ $invoice->cancellation_fee }}</td>
        <td>{{ $invoice->user->companies_titles }}</td>
            </tr>
        @endforeach


the result now is

1   xxxxx   name    name    price   price   company1
1   xxxxx   name    name    price   price   company4
1   xxxxx   name    name    price   price   company1
1   xxxxx   name    name    price   price   company3
1   xxxxx   name    name    price   price   company5
1   xxxxx   name    name    price   price   company2
1   xxxxx   name    name    price   price   company1

is it possilb e to get it with

1   xxxxx   name    name    price   price   company1
1   xxxxx   name    name    price   price   company1
1   xxxxx   name    name    price   price   company1
1   xxxxx   name    name    price   price   company2
1   xxxxx   name    name    price   price   company3
1   xxxxx   name    name    price   price   company4
1   xxxxx   name    name    price   price   company5

SandraCarlsen's avatar

@ftiersch Thanks, will this be in the blade? as

        @foreach($invoices->sortBy(function ($invoice) {
    return $invoice->user->companies_title;
});

really appreciate the help

ftiersch's avatar

You could use it in the blade but it wouldn't be very easily readable. I'd put it in the controller and then pass the sorted $invoices collection to the blade so there you only need to do

@foreach ($invoices as $invoice)
SandraCarlsen's avatar

@ftiersch Thank you. When I put it in my controller


        $invoices = Invoice::where('course_occasion_id', $courseOccasionId)->get();
$invoices->sortBy(function ($invoice) {
    return $invoice->user->companies_title;
});

is not working, do I have to combine it in the get? Sorry for all the newbie questions

ftiersch's avatar
ftiersch
Best Answer
Level 28

sortBy works a little different than in JS I think :) It doesn't actually change the original collection but returns a new collection. So you could do this:

$invoices = Invoice::where('course_occasion_id', $courseOccasionId)->get()->sortBy(function ($invoice) {
    return $invoice->user->companies_title;
});
1 like
skauk's avatar

I see a way to optimize it a bit further. Since you'd be retrieving data from the User model for sorting you'd be doing an additional database query for each of your invoices. To address that you can eager load relevant User data in advance, performing just two database query for the same result:

$invoices = Invoice::with('user:companies_title')
    ->where('course_occasion_id', $courseOccasionId)
    ->get()
    ->sortBy('user.companies_title');

Notice that you only getting companies_title attribute from User model and the closure in sortBy() method is now gone as you have that data now included into Invoice model.

1 like
SandraCarlsen's avatar

@ftiersch Thanks this is what I really was looking for. This made it so much simple to undserstand. You made my day :-)

@skauk this was very intressting. I will definitly use this knowledge. I am useing more than the companies title from the user table but I can see the advantage in loading and so forth. Thank you very much for your time.

Thank you all, issue solved

Please or to participate in this conversation.