Search code examples
phparraysmultidimensional-arraygrouping

Group objects in an array of objects by a column value and create a subarray of objects in each group


I have the following query result:

Array
(
    [0] => stdClass Object
        (
            [TreatmentLog_ID] => 131
            [DateAdministered] => 2016-07-15
            [Notes] => 
            [Treatment_ID] => 144
            [AmountAdministered] => 1.5
            [Injectable_ID] => 2
            [InjectableName] => Baytril
        )

    [1] => stdClass Object
        (
            [TreatmentLog_ID] => 133
            [DateAdministered] => 2016-07-12
            [Notes] => 
            [Treatment_ID] => 146
            [AmountAdministered] => 1.2
            [Injectable_ID] => 20
            [InjectableName] => Vitamin C
        )

    [2] => stdClass Object
        (
            [TreatmentLog_ID] => 133
            [DateAdministered] => 2016-07-12
            [Notes] => 
            [Treatment_ID] => 147
            [AmountAdministered] => 1.3
            [Injectable_ID] => 21
            [InjectableName] => Vitamin E
        )
)

I'd like to be able to restructure the array into something like this:

Array
(
    [0] => stdClass Object
        (
            [TreatmentLog_ID] => 131
            [DateAdministered] => 2016-07-15
            [Notes] => 
            [Treatments] => Array
                (
                    [0] => stdClass Object
                        (
                            [Treatment_ID] => 144
                            [AmountAdministered] => 1.5
                            [Injectable_ID] => 2
                            [InjectableName] => Baytril
                        )

                )

        )

    [1] => stdClass Object
        (
            [TreatmentLog_ID] => 133
            [DateAdministered] => 2016-07-12
            [Notes] => 
            [Treatments] => Array
                (
                    [0] => stdClass Object
                        (
                            [Treatment_ID] => 146
                            [AmountAdministered] => 1.2
                            [Injectable_ID] => 20
                            [InjectableName] => Vitamin C
                        )

                    [1] => stdClass Object
                        (
                            [Treatment_ID] => 147
                            [AmountAdministered] => 1.3
                            [Injectable_ID] => 21
                            [InjectableName] => Vitamin E
                        )

                )

        )

)

Notice how the second array looks merges the InjectableName, AmountAdministered, Injectable_ID, and Treatment_ID into the array Treatments if the TreatmentLog_ID is a match. Typically working with arrays isn't a problem, but this one has me stumped. Also I cannot change the query.

How could I pull this off in PHP?


Solution

  • The solution using isset and array_values functions:

    // $arr is your initial array
    $result = [];
    foreach ($arr as $obj) {
        $innerObj = (object)[ 'Treatment_ID' => $obj->Treatment_ID, 'AmountAdministered' => $obj->AmountAdministered,
                              'Injectable_ID' => $obj->Injectable_ID, 'InjectableName' => $obj->InjectableName ];
    
        if (!isset($result[$obj->TreatmentLog_ID])) {
            $result[$obj->TreatmentLog_ID] = (object)[
                'TreatmentLog_ID' => $obj->TreatmentLog_ID,
                'DateAdministered' => $obj->DateAdministered,
                'Notes' => $obj->Notes,
                'Treatments' => [$innerObj]
            ];
        } else {
            $result[$obj->TreatmentLog_ID]->Treatments[] = $innerObj;
        }
    }
    
    $result = array_values($result);
    print_r($result);  // will output the expected result