复杂的Laravel系列

时间:2017-03-15 08:13:07

标签: php arrays laravel laravel-5 collections

我在使用Laravel Collection类时遇到了一些问题。

我正在尝试做什么:

  • 我有一个多站点解决方案,其中一个站点有“促进者”。有时一个辅导员出现在多个站点上,而不仅仅是一个。
  • 我想列出他们在主页上的所有主持人和网站,但我不想要多个用户。

所以我目前所做的是:

  • 获得辅导员。
  • 使用Collection收集辅导员并使用unique('name')

这给了我独特的促进者,但只挑选了它检测到的第一个,然后删除了其他的。

所以我想说我有这个系列:

Collection { 
  #items: array:3 [
    0 => array:2 [
      "name" => "John"
      "site" => "Example"
    ]
    1 => array:2 [
      "name" => "Martin"
      "site" => "Another"
    ]
    2 => array:2 [
      "name" => "John"
      "site" => "Another"
    ]
  ]
}

unique()我会得到:

Collection { 
  #items: array:3 [
    0 => array:2 [
      "name" => "John"
      "site" => "Example"
    ]
    1 => array:2 [
      "name" => "Martin"
      "site" => "Another"
    ]
  ]
}

这就是我想要的:

Collection { 
  #items: array:3 [
    0 => array:2 [
      "name" => "John"
      "site" => ["Example", "Another"]
    ]
    1 => array:2 [
      "name" => "Martin"
      "site" => "Another"
    ]
  ]
}

有没有人知道如何用Laravel的集合类来实现这个目标?

2 个答案:

答案 0 :(得分:3)

如果坚持使用收藏品,请记住reduce是您工具库中的强大工具。

基于Sam的答案,我无法开始工作,我认为使用reduce和groupBy应该有效...

$sites = collect([
  ["name" => "John", "site" => "Example"],
  ["name" => "Martin", "site" => "Another"],
  ["name" => "John", "site" => "Another"],
]);

$sites->groupBy('name')->reduce(function ($result, $item) {
  $result[] = [
    'name' => $item->first()['name'], 
    'sites' => $item->pluck('site')->toArray()
  ];

  return $result;
}, collect([]))->toArray();

从控制台......

λ php artisan tinker                                                                             
Psy Shell v0.8.2 (PHP 7.0.10 ÔÇö cli) by Justin Hileman                                          
>>> $sites = collect([                                                                           
...   ["name" => "John", "site" => "Example"],                                                   
...   ["name" => "Martin", "site" => "Another"],                                                 
...   ["name" => "John", "site" => "Another"],                                                   
... ]);                                                                                          
=> Illuminate\Support\Collection {#698                                                           
     all: [                                                                                      
       [                                                                                         
         "name" => "John",                                                                       
         "site" => "Example",                                                                    
       ],                                                                                        
       [                                                                                         
         "name" => "Martin",                                                                     
         "site" => "Another",                                                                    
       ],                                                                                        
       [                                                                                         
         "name" => "John",                                                                       
         "site" => "Another",                                                                    
       ],                                                                                        
     ],                                                                                          
   }                                                                                             
>>> $sites->groupBy('name')->reduce(function ($result, $item) {                                  
...   $result[] = ['name' => $item->first()['name'], 'sites' => $item->pluck('site')->toArray()];
...                                                                                              
...   return $result;                                                                            
... }, collect([]))->toArray();                                                                  
=> [                                                                                             
     [                                                                                           
       "name" => "John",                                                                         
       "sites" => [                                                                              
         "Example",                                                                              
         "Another",                                                                              
       ],                                                                                        
     ],                                                                                          
     [                                                                                           
       "name" => "Martin",                                                                       
       "sites" => [                                                                              
         "Another",                                                                              
       ],                                                                                        
     ],                                                                                          
   ]                                                                                             

有一点需要注意的是,您在问题中指出,如果只有一个网站,则网站应返回单个字符串,如果有多个网站,则返回一个数组。上述解决方案不提供此功能!我认为这是不一致的,你应该总是为站点键返回一个数组,即使它只有一个值,因为它会使以后更难以阅读和操作。

但是,如果这很重要,您可以使用pluck设置数组来检查是否有很多站点,如果不是,您可以将其设置为单个字符串,如下所示:

$sites->groupBy('name')->reduce(function ($result, $item) {
  $result[] = [
    'name' => $item->first()['name'],
    'sites' => $item->pluck('site')->count() > 1 ? $item->pluck('site') : $item->first()['site']
  ];

  return $result;
}, collect([]))->toArray();

会产生......

[                        
  [                      
    "name" => "John",    
    "sites" => [         
      "Example",         
      "Another",         
    ],                   
  ],                     
  [                      
    "name" => "Martin",  
    "sites" => "Another",
  ],                     
]                        

答案 1 :(得分:0)

你可以通过链接来获得你想要的东西,假设$ collection是主要的集合

 $collection->groupBy('name')->map(function($facilitators) {
     return ['name' => $facilitators->first()['name'], 'site' => $facilitators->pluck('site')->toArray()];
})->values()->toArray();

首先按名称分组,这样它将在集合内部给出二维数组,然后迭代到那个名称将是常见的,所以从第一个元素获取它,然后从所有元素pluck网站获取并将其转换为数组,使用flatMap将使它单层嵌套。