Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

balmac's avatar

Collections: Multiple Higher Order Messages

Can anyone explain why I can not combine multiple map calls using higher order messages? I thought they were just shortcuts, but apparently it's not that simple.

For example I want to filter all students that are older than 10 in multidimensional array of Teacher -> Class -> Students. I thought I should be able to use map->map->filter but that does not work, I get an exception: "Cannot use object of type Illuminate\Support\HigherOrderCollectionProxy as array". Strangely enough it works if I use map->map->map->filter, but the students are only 2 levels deep?

Example: https://laravelplayground.com/#/snippets/fbef1347-1242-4fcc-b875-d03aad6e1b44

0 likes
7 replies
webrobert's avatar

why not just...

$students = collect([
        ['teacher' => 'Teacher 1', 'class' => 'Class A', 'name' => 'Student 1', 'age' => 10],
        ['teacher' => 'Teacher 1', 'class' => 'Class A', 'name' => 'Student 2', 'age' => 11],
        ['teacher' => 'Teacher 1', 'class' => 'Class A', 'name' => 'Student 3', 'age' => 12],
        ['teacher' => 'Teacher 1', 'class' => 'Class B', 'name' => 'Student 1', 'age' => 12],
        ['teacher' => 'Teacher 1', 'class' => 'Class B', 'name' => 'Student 2', 'age' => 13],
        ['teacher' => 'Teacher 1', 'class' => 'Class B', 'name' => 'Student 3', 'age' => 9],
        ['teacher' => 'Teacher 2', 'class' => 'Class C', 'name' => 'Student 1', 'age' => 6],
        ['teacher' => 'Teacher 2', 'class' => 'Class C', 'name' => 'Student 2', 'age' => 7],
    ])
    ->filter( fn($class) => $class['age'] > 10)
    ->groupBy(['teacher', 'class']);
balmac's avatar

This is just an example. In practice the filter is not so simple and I need to have the grouping first (applied to this example it could be filter by average age of all students within a class/teacher).

balmac's avatar

@webrobert The data is not even coming from a database so there is no query.

This is not really a question to get a problem solved (It obviously works by just writing out map->function()... It really is a question about understanding why higher order messages are behaving the way they are, which seems at least very counterintuitive.

webrobert's avatar

@balmac well the way they work is ....

each higher order message can be accessed as a dynamic property on a collection instance.

note: on a collection instance

Without digging into what is happen I suspect that your triple map is creating a collection instance that can be dynamic. where the double hasn't. 🙃

webrobert's avatar

so with that in mind, this works too...

return $students->groupBy('teacher')
 	->map->groupBy('class')
	->map->where('age', '<', 10);
balmac's avatar

@webrobert Yes I assume this is what's happening.

My thinking is now that every call to a High Order Function returns a proxy which needs to be "resolved" by a non-Higher Order Function. Strangely this happens with an extra map call as well.

Please or to participate in this conversation.