Search code examples
laraveleloquentcollection-select

Dynamic Collection Mapping: Add missing records in collection


I have the following

->select(DB::raw('source as Source, customer as Customers, COUNT(*) as count'))
->groupBy('source', 'customer')
->get();

I get the follwing results

Illuminate\Support\Collection {#460 ▼
  #items: array:4 [▼
    0 => {#466 ▼
      +"Source": "Facebook"
      +"Customer": "Yes"
      +"count": 227
    }
    1 => {#463 ▼
      +"Source": "PinInterest"
      +"Customer": "Yes"
      +"count": 370
    }
    2 => {#465 ▼
      +"Source": "PinInterest"
      +"Customer": "No"
      +"count": 133
    }
    3 => {#467 ▼
      +"Source": "Whatsapp"
      +"Customer": "No"
      +"count": 254
    }
  ]
}

Now Source can be 1 - 10 different channels depending on the customer. Now Customer Be Yes or No.

How do I add modify collection to add Source Facebook, Customer No and Count 0, and Source WhatsApp, Customer Yes and Count 0

Source : Facebook Customer : Yes Count : 227

Source : Facebook Customer : No Count : 0

Source : Whatsapp Customer : No count : 254

Source : Whatsapp Customer : Yes count : 0


Solution

  • Using laravel's collection helpers you can add missing data in your original collection as

    Transformation

    /** Result from original query */
    $collection = collect([
        ["Source"=>"Facebook","Customer"=> "Yes","count"=> 227],
        ["Source"=>"PinInterest","Customer"=> "Yes","count"=> 370],
        ["Source"=>"PinInterest","Customer"=>"No","count"=> 133],
        ["Source"=>"Whatsapp","Customer"=> "No","count"=>254]
      ]);
    
    /** Unique list of sources */
    $sources = $collection->pluck('Source')->unique();
    
    /** Unique list of customers */
    $customers = collect(["Yes","No","May Be"]);
    
    $sources->each(function ($source, $sourceKey) use (&$collection,$customers) {
        if($collection->where('Source', $source)->count() < count($customers)){
            $customers->each(function ($customer, $customerKey) use (&$collection,$source) {
                if($collection->where('Source', $source)->where('Customer', $customer)->count() === 0){
                    $collection = $collection->merge([["Source"=>$source,"Customer"=> $customer,"count"=>0]]);                
                }
            });
        }
    });
    
    /** Sort and print */
    echo "<pre>";
    print_r($collection->sortBy('Source')->toArray());
    echo "</pre>";
    

    Output

    Array
    (
        [0] => Array
            (
                [Source] => Facebook
                [Customer] => Yes
                [count] => 227
            )
    
        [4] => Array
            (
                [Source] => Facebook
                [Customer] => No
                [count] => 0
            )
    
        [5] => Array
            (
                [Source] => Facebook
                [Customer] => May Be
                [count] => 0
            )
    
        [1] => Array
            (
                [Source] => PinInterest
                [Customer] => Yes
                [count] => 370
            )
    
        [2] => Array
            (
                [Source] => PinInterest
                [Customer] => No
                [count] => 133
            )
    
        [6] => Array
            (
                [Source] => PinInterest
                [Customer] => May Be
                [count] => 0
            )
    
        [3] => Array
            (
                [Source] => Whatsapp
                [Customer] => No
                [count] => 254
            )
    
        [7] => Array
            (
                [Source] => Whatsapp
                [Customer] => Yes
                [count] => 0
            )
    
        [8] => Array
            (
                [Source] => Whatsapp
                [Customer] => May Be
                [count] => 0
            )
    
    )