Filter, Map, and Exists


We've covered the more commonly used methods in the previous two videos, so now it's time to see the more powerful - and less commonly seen - methods.

In this video we will cover:

  • exists
  • filter
  • map

The most likely reason that these functions are not used is that the documentation, in my opinion, doesn't help you understand how these methods can be used.

There's a confusing element to each of these method signatures in that we are expected to give a Closure $p, which in itself sounds confusing and scary. If you do figure out that the Closure $p refers to passing in a function, the next confusing step is that you might not be aware that this Closure (or function) receives one or more variables by default.

If you come from a JavaScript (or similar) background, you will be likely quite comfortable with the concept of a method taking an anonymous function as a parameter.

To clarify, an anonymous function is simply a function without a name.

Let's say we have the following function:

function hello($name = 'World') {
    echo 'hello ' . $name . '!';
}

hello(); // output - hello World!
hello('tony'); // output - hello tony!

Here we are passing in a variable to our function. So far, so easy.

What if wanted to pass in an array of names to say hello too?

Well, we could write this a few ways, two of which would be:

function hello($name = 'World') {
    echo 'hello ' . $name . '!';
}

$names = ['bob', 'ben', 'bill'];

// the 'normal' way

foreach($names as $name) {
    hello($name);
}

// or

array_map("hello", $names);

If you're not familiar with array_map then do check out the official PHP documentation.

In non-computer-textbook speak, we are taking a function and applying that function to each item in our array. Or, the boffin way would be to say we are mapping a function on to our array.

The function we map on to our array loops through each item in the array, taking the current item in the array as its parameter, and then calling that function with that parameter.

However, so far we haven't used anonymous functions at all. Instead, we have made a named function:

function hello($name = 'World') // * snip * - a named function

And then 'called' that function by name in our array_map function:

array_map("hello", $names);

If we aren't going to re-use that hello function, there's no point in it hanging around.

Instead, we can put the function in-line. This time it won't have a name. It is anonymous:

$names = ['bob', 'ben', 'bill'];

array_map(function($name){
  echo 'hello ' . $name . '!';
}, $names);

This really isn't that prevalent in PHP-land in my experience, but it is very cool and handy to know about. If you do much JavaScript currently, or wish to do so in the future, you will likely see this more frequently.

Wasn't This A Doctrine Collection Video?

Aha, well spotted. All this talk of array_map and anonymous functions and we have seemingly skipped the video topic entirely.

I mention all this for three reasons.

Firstly, I want to show you that the concept of in-line / anonymous functions are not that scary. Once you understand the basic usage pattern they do become apparently useful in a number of common situations, especially if you deal with arrays. And we all deal with arrays :)

Secondly, the Collection functions like filter, map, exists, and so on all take an anonymous function as part of their method call. If you don't understand how to use them outside of Doctrine, it can be really complicated and tricky to use them with a Collection. And if things are complicated and tricky they are either prone to bugs or long winded workarounds.

And thirdly, under the hood, ArrayCollection is calling array_map and array_filter for us. If we don't understand the usage pattern then a convenience method is absolutely no use to us.

Episodes