Laravel group by and unique values for each group

I have a table for Specifications and the table contains specification_key , specification_value.

I’m trying to group all specifications by the specification_key and also each group must contain only unique values.

I tried:

        $specifications = Specification::whereIn('product_id', $products->pluck('id'))->get();

        $SpecsGroup = $specifications->groupBy('specification_key');

        dd($SpecsGroup);

This returns groups by specification_key but these contain the same specification_value multiple times.

IlluminateDatabaseEloquentCollection {#1572 ▼
    #items: array:12 [▼
      "RAM" => IlluminateDatabaseEloquentCollection {#1522 ▼
        #items: array:4 [▼
          0 => AppModelsSpecification {#1607 ▼
            #attributes: array:6 [▼
              "id" => 1
              "product_id" => 1
              "specification_key" => "RAM"
              "specification_value" => "16 GB"
              "created_at" => "2021-03-21 15:35:21"
              "updated_at" => "2021-03-21 15:35:21"
            ]
          }
          1 => AppModelsSpecification {#1586 ▼
            #attributes: array:6 [▼
              "id" => 51
              "product_id" => 2
              "specification_key" => "RAM"
              "specification_value" => "16 GB"
              "created_at" => "2021-04-16 15:38:23"
              "updated_at" => "2021-04-16 15:38:23"
            ]
          }
          2 => AppModelsSpecification {#1584 ▼
            #attributes: array:6 [▼
              "id" => 55
              "product_id" => 3
              "specification_key" => "RAM"
              "specification_value" => "8 GB"
              "created_at" => "2021-04-16 16:36:03"
              "updated_at" => "2021-04-16 16:36:03"
            ]
          }
          3 => AppModelsSpecification {#1494 ▶}
        ]
      }
      "Brand" => IlluminateDatabaseEloquentCollection {#1503 ▶}
      "Manufacturer" => IlluminateDatabaseEloquentCollection {#1562 ▶}
      "Model" => IlluminateDatabaseEloquentCollection {#1563 ▶}
      "Model Year" => IlluminateDatabaseEloquentCollection {#1564 ▶}
      "Product Dimensions" => IlluminateDatabaseEloquentCollection {#1565 ▶}
      "Model Name" => IlluminateDatabaseEloquentCollection {#1566 ▶}
      "LED" => IlluminateDatabaseEloquentCollection {#1567 ▶}
      "Size" => IlluminateDatabaseEloquentCollection {#1568 ▶}
      "Pack" => IlluminateDatabaseEloquentCollection {#1569 ▶}
      "Fan Controller" => IlluminateDatabaseEloquentCollection {#1570 ▶}
      "Warranty" => IlluminateDatabaseEloquentCollection {#1571 ▶}
    ]
  }
 

I want the values to be unique as in the above it currently returning the same specification_value multiple times.

Like if it has “16 GB RAM” 2 times it should return 1 only 1 time “16 GB RAM”

How can I do that?

Thanks in advance, I’ve been trying this for the last 2 hours :(, now StackOverflow is the last hope.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You can do simply this way:

$data = Specification::whereIn('product_id', $products->pluck('id'))
    ->groupBy(['specification_key', 'specification_value']) // group by query
    ->get()
    ->groupBy('specification_key'); // group by collection
array:1 [
  "RAM" => array:2 [
    0 => array:6 [
      "id" => 1
      "product_id" => 1
      "specification_key" => "RAM"
      "specification_value" => "16 GB"
      "created_at" => "2021-03-21T15:35:21.000000Z"
      "updated_at" => "2021-03-21T15:35:21.000000Z"
    ]
    1 => array:6 [
      "id" => 3
      "product_id" => 3
      "specification_key" => "RAM"
      "specification_value" => "8 GB"
      "created_at" => "2021-04-16T16:36:03.000000Z"
      "updated_at" => "2021-04-16T16:36:03.000000Z"
    ]
  ]
]

If you have problem with Syntax error or access violation: 1055, you can follow this answer.

Edit your applications’s database config file config/database.php

In mysql array, set strict => false to disable MySQL’s strict mode


If you want to display specification_value only, you can use mapToGroups() :

$data = Specification::whereIn('product_id', $products->pluck('id'))
    ->groupBy(['specification_key', 'specification_value']) // group by query
    ->get()
    ->mapToGroups(function ($item, $key) {
        return [$item['specification_key'] => $item['specification_value']];
    });
array:1 [
  "RAM" => array:2 [
    0 => "16 GB"
    1 => "8 GB"
  ]
]

Method 2

After trying for hours I got this myself, I’m still not sure how I did this but it works. 😀

        $specifications = Specification::whereIn('product_id', $products->pluck('id'))
        ->distinct('specification_value')
        ->groupBy('specification_value')
        ->distinct('specification_key')
        ->groupBy('specification_key')
        ->get()
        ->groupBy('specification_key');

Method 3

Use this code:

$spec_values = ['8 GB', '16 GB'];
$SpecsGroup = collect();
foreach($spec_values as $spec_value) {
    $SpecGroup = Specification::whereIn('product_id', $products->pluck('id'))->where('specification_value', $spec_value)->first();
    if ($SpecGroup !== null) {
        $SpecsGroup->push($SpecGroup);
    }
}
dd($SpecsGroup);

Method 4

You can use ->unique()

$specifications = Specification::whereIn('product_id', $products->pluck('id'))->unique();


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x