skip to Main Content

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');
    }

2

Answers


  1. Chosen as BEST ANSWER
    public function GetCustomerBodySize($customerId, $month, $year)
        {
            $customerUserId = Customer::findOrFail($customerId)['user'];
    
            $data = 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();
    
            // this did the job for me
            $data = $data->toArray();
    
            $groupedUserBodySizes = collect($data['customer_data']['user_body_sizes'])->groupBy('measured_at')->values()->toArray();
    
            $data['customer_data']['user_body_sizes'] = $groupedUserBodySizes;
    
            return $data;
        }
    

  2. you can use Laravel's Collection’s groupBy() method to group the user_body_sizes by their measured_at date

    1. we are first fetching all the relevant CustomerBodySize records with the given filters using get() instead of first()

    2. And then we make group user_body_sizes by their measured_at date using the groupBy() method

    3. At last, we use map() to return an array of arrays, with each nested array containing the CustomerBodySize records that share the same measured_at date. We also use values() to remove the grouping keys from the resulting collection.

    4. If there are no records matching the given filters, we return null .

    Modified Code is Here

    public function GetCustomerBodySize($customerId, $month, $year)
    
    {
    
    $customerUserId = Customer::findOrFail($customerId)['user'];
    
    $bodySizes = 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)
    ->get();
    
    $groupedBodySizes = $bodySizes->groupBy(function ($item) {
        return $item->measured_at;
    });
    
    $result = $groupedBodySizes->map(function ($item) {
        return $item->values();
    })->values();
    
    return $result->isEmpty() ? null : $result->first();
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search