2

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.

Illuminate\Database\Eloquent\Collection {#1572 ▼
    #items: array:12 [▼
      "RAM" => Illuminate\Database\Eloquent\Collection {#1522 ▼
        #items: array:4 [▼
          0 => App\Models\Specification {#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 => App\Models\Specification {#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 => App\Models\Specification {#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 => App\Models\Specification {#1494 ▶}
        ]
      }
      "Brand" => Illuminate\Database\Eloquent\Collection {#1503 ▶}
      "Manufacturer" => Illuminate\Database\Eloquent\Collection {#1562 ▶}
      "Model" => Illuminate\Database\Eloquent\Collection {#1563 ▶}
      "Model Year" => Illuminate\Database\Eloquent\Collection {#1564 ▶}
      "Product Dimensions" => Illuminate\Database\Eloquent\Collection {#1565 ▶}
      "Model Name" => Illuminate\Database\Eloquent\Collection {#1566 ▶}
      "LED" => Illuminate\Database\Eloquent\Collection {#1567 ▶}
      "Size" => Illuminate\Database\Eloquent\Collection {#1568 ▶}
      "Pack" => Illuminate\Database\Eloquent\Collection {#1569 ▶}
      "Fan Controller" => Illuminate\Database\Eloquent\Collection {#1570 ▶}
      "Warranty" => Illuminate\Database\Eloquent\Collection {#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.

Aniket Das
  • 367
  • 1
  • 6
  • 17

4 Answers4

2

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"
  ]
]
Wahyu Kristianto
  • 8,719
  • 6
  • 43
  • 68
1

After trying for hours I got this myself, I'm still not sure how I did this but it works. :D

        $specifications = Specification::whereIn('product_id', $products->pluck('id'))
        ->distinct('specification_value')
        ->groupBy('specification_value')
        ->distinct('specification_key')
        ->groupBy('specification_key')
        ->get()
        ->groupBy('specification_key');
Aniket Das
  • 367
  • 1
  • 6
  • 17
0

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);
Hedayatullah Sarwary
  • 2,664
  • 3
  • 24
  • 38
-3

You can use ->unique()

$specifications = Specification::whereIn('product_id', $products->pluck('id'))->unique();
Wahyu Kristianto
  • 8,719
  • 6
  • 43
  • 68
user123
  • 9
  • 2