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

moemenh_'s avatar

Laravel how to put related columns with the same date in an array

I am at the moment calling a few nested relations. But what I am trying to do is to get all the columns with the same "measured_at" date in one array instead of them being spread.

A brief example of the structure that I am getting:

{
    "id": 1,
    "user_body_sizes": [
        {
            "id": 23,
            "measured_at": "2023-04-04"
        },
        {
            "id": 24,
            "measured_at": "2023-04-04"
        },
        {
            "id": 26,
            "measured_at": "2023-03-14"
        },
        {
            "id": 29,
            "measured_at": "2023-03-14"
        }
    ]
}

So this is what I actually want to achieve:

{
    "id": 1,
    "user_body_sizes": [
        [
            {
                "id": 23,
                "measured_at": "2023-04-04"
            },
            {
                "id": 24,
                "measured_at": "2023-04-04"
            }
        ],
        [
            {
                "id": 29,
                "measured_at": "2023-03-14"
            },
            {
                "id": 26,
                "measured_at": "2023-03-14"
            }
        ]
    ]
}

So basically I want the data with the same "measured_at" date to be in the same array.

So in Laravel this is my code at the moment to get the data:

public function GetCustomerBodySize($customerId, $month, $year)
    {
        $customerUserId = Customer::findOrFail($customerId)['user'];

        return CustomerBodySize::with([ 'customer_data.user_body_sizes.body_parts','customer_data.user_body_sizes' => function ($q) use ($month, $year){
            $q->whereMonth('measured_at', '=', $month);
            $q->whereYear('measured_at', '=', $year);
            $q->orderBy('measured_at');
        }])
            ->whereRelation('customer_data', 'id', $customerUserId)
            ->first();
    }

And here are my relations:

// This is in my CustomerBodySize model
function customer_data(){
        return $this->belongsTo(User::class, 'customer');
    }

function body_parts(){
        return $this->belongsTo(BodyParts::class, 'body_part');
    }

// This is in my User model
public function user_body_sizes(){
        return $this->hasMany(CustomerBodySize::class, 'customer');
    }
0 likes
1 reply
LaryAI's avatar
Level 58

To achieve the desired result, you can use the Laravel collection's groupBy method to group the related models by their "measured_at" date. Here's an updated version of the GetCustomerBodySize method that should work:

public function GetCustomerBodySize($customerId, $month, $year)
{
    $customerUserId = Customer::findOrFail($customerId)['user'];

    $bodySizes = CustomerBodySize::with(['customer_data.user_body_sizes.body_parts'])
        ->whereRelation('customer_data', 'id', $customerUserId)
        ->whereMonth('measured_at', '=', $month)
        ->whereYear('measured_at', '=', $year)
        ->orderBy('measured_at')
        ->get()
        ->groupBy('measured_at')
        ->values()
        ->map(function ($group) {
            return $group->map(function ($item) {
                return $item->customer_data->user_body_sizes;
            });
        });

    return $bodySizes->isEmpty() ? null : $bodySizes->first();
}

Here's what's happening in the updated code:

  • We're using the groupBy method to group the related models by their "measured_at" date.
  • We're using the values method to remove the keys from the resulting collection.
  • We're using the map method to transform each group into an array of user_body_sizes models.
  • We're returning the first group, or null if the collection is empty.

Note that we're using the get method instead of first to retrieve all the related models, since we need to group them before returning the result.

Please or to participate in this conversation.