Dados os seguintes dados:
manufacturers makes
id | name id | manufacturer_id | name
---|----- -- | --------------- | ----
1 | Honda 1 | 1 | Honda
2 | Toyota 2 | 1 | Acura
3 | Mazda 3 | 2 | Toyota
4 | Other 4 | 2 | Lexus
5 | 3 | Mazda
6 | 4 | Other
Estou tentando obter uma matriz parecida com esta:
[
"Honda" => [1 => "Honda", 2 => "Acura"],
"Toyota" => [3 => "Toyota", 4 => "Lexus"],
5 => "Mazda",
6 => "Other",
]
Em outras palavras, agrupe por fabricante, mas somente se o fabricante tiver mais de uma marca. O método para especificar essa condição está me escapando. Até agora, consegui o seguinte:
Make::with("manufacturer")
->get()
->groupBy(
fn (Make $m) => $m->manufacturer->models->count() < 2 ? null : $m->manufacturer->name
)
->map(
fn (Collection $c) => $c->mapWithKeys(
fn (Make $m) => [$m->id => $m->name]
)
)
->toArray();
Eu esperava que retornar null
do groupBy
retorno de chamada impedisse o agrupamento, mas não tive sorte. Isso me dá o seguinte:
[
"" => [5 => "Mazda", 6 => "Other"]
"Honda" => [1 => "Honda", 2 => "Acura"],
"Toyota" => [3 => "Toyota", 4 => "Lexus"],
]
Então, eu quero uma maneira de agrupar condicionalmente desde o início, ou nivelar condicionalmente após o agrupamento. Sei que posso fazer isso manualmente, mas parece que deveria haver um método Collection integrado para isso.
Você pode usar
groupBy('manufacturer.name')
agrupar por nome do fabricante.flatMap
usado para verificar se cada fabricante tem mais de uma marcaRetornando
null
degroupBy
grupos fabricantes de marca única sob uma chave "" (string vazia), o que não é o que você deseja. O groupBy do Laravel não pula nativamente o agrupamento para determinados itens, e não há um método de coleta direta para agrupar condicionalmente apenas alguns elementos.Você pode agrupar todas as marcas por fabricante e, em seguida, realizar um pós-processamento para simplificar os grupos de marcas individuais:
A solução mais concisa que encontrei foi esta: