Passing Data to PHP Anonymous Functions

PHP

PHP version 5.3 introduced a new feature called anonymous functions, or lambda functions. You may have come across them in other languages such as C# or Ruby. They allow for greater flexibility and offer a clean, expressive syntax.

Anonymous functions are passed as arguments to other functions, and in this context they are usually referred to as callbacks. Let's look at a really simple example of this using PHP's array_filter function:

<?php

// This is just creating a really simple array.
$myArray = array('a', 'really', 'simple', 'array');

// Call the array_filter function using our really simple array and a
// custom callback.
$myNewArray = array_filter($myArray, function($value) {
    return $value != 'a';
});

If we run the above code our really simple array will only have three values: 'really', 'simple', 'array'. This is because in our callback (anonymous functinon) we said that if the $value != 'a' to return true (when $value is 'a' our expression returns false). When we return true from our anonymous function, the array_filter function will keep the value in the array, and if we return false from our anonymous function the value is not added to our new array.

For the purpose of this post, let's say we wanted to store the the value to check against in its own variable like this:

<?php

// This is just creating a really simple array.
$myArray = array('a', 'really', 'simple', 'array');


$valueToCheckAgainst = 'a';

// Call the array_filter function using our really simple array and a
// custom callback.
$myNewArray = array_filter($myArray, function($value) {
    return $value != $valueToCheckAgainst;
});

If we try to run this we code we will get an error similar to this:

Notice: Undefined variable: valueToCheckAgainst

But how come? We obviously declared the variable and we gave it a value! Surely PHP must be playing tricks on us!

Drama aside, the reason PHP gives us the error is because anonymous functions execute in a different scope than our regular code so our anonymous functinon cannot 'see' any of the variables we've declared outside of the anonymous function. To resolve this, we must use the use keyword. That looks like this:

<?php

// This is just creating a really simple array.
$myArray = array('a', 'really', 'simple', 'array');


$valueToCheckAgainst = 'a';

// Call the array_filter function using our really simple array and a
// custom callback.
$myNewArray = array_filter($myArray, function($value) use ($valueToCheckAgainst) {
    return $value != $valueToCheckAgainst;
});

That's all we have to do to make a variable available to our anonymous function when we cannot alter the number of parameters or anonymous function can have.

Tip: you can pass multiple variables to your anonymous function with the use keyword by separating them with a comma:

<?php

// This is just creating a really simple array.
$myArray = array('a', 'really', 'simple', 'array');


$valueToCheckAgainst = 'a';
$valueToCheckAgainst2 = 'b';
$valueToCheckAgainst3 = 'c';

// Call the array_filter function using our really simple array and a
// custom callback.
$myNewArray = array_filter($myArray, function($value) use ($valueToCheckAgainst, $valueToCheckAgainst2, $valueToCheckAgainst3) {
    return in_array($value, [
        $valueToCheckAgainst, $valueToCheckAgainst2, $valueToCheckAgainst3
    ]);
});

Join the Discussion

Leave a comment

  • Jeff Cohan
    Jeff Cohan
    June 7, 2016 2:32 PM Reply

    This saved me from scratching my hair out. I tried using global $variable;, but that didn't work Question about your example with multiple use variables: The test in the anonymous function >references only one of the used variables. What's the benefit of adding the 2nd and 3rd variables in your example?

      John
      John
      June 7, 2016 2:54 PM Reply

      Hi Jeff, Thanks for taking the time to leave your thoughts. That example was to demonstrate the syntax of passing multiple variables into an anonymous function of Closure. I've updated the example code to make use of the variables for readers in the future. John

  • Jeff Cohan
    Jeff Cohan
    June 7, 2016 5:10 PM Reply

    Thanks, John. That makes sense. And now array_filter() is much more useful to me, thanks to your explanation.

  • Jeff Cohan
    Jeff Cohan
    June 7, 2016 7:14 PM Reply

    Hmmm... I'm getting closer. I'm trying to add a !in_array() test in my anonymous function, and I added the array name ($org_ids, a numeric array) to the use clause. But it's not working. return !in_array($val, $org_ids); It's as if you had, in your example, created an array like this: $check_against = array('a', 'b', 'c'); and then did... return in_array($value, $check_against); Is there some related namespace issue with anonymous functions with respect to arrays? Thanks for you help and patience.

      John
      John
      June 8, 2016 5:35 AM Reply

      No special namespaces are required to use PHP's array_* functions. This code snippet here:

      $myNewArray = array_filter($myArray, function($value) use ($valueToCheckAgainst, $valueToCheckAgainst2, $valueToCheckAgainst3) {
      return in_array($value, [
      $valueToCheckAgainst, $valueToCheckAgainst2, $valueToCheckAgainst3
      ]);
      });
      

      is technically creating an array, just not using the array function. It is using the short array syntax (described here (opens in a new window)). The short syntax is available on PHP versions 5.4 and up.

      The following two lines are equivalent:

      $array = array('a', 'b', 'c');
      $array = ['a', 'b', 'c'];
      

      In the context of the original post, the following two examples are the same:

      // Using array short syntax (PHP 5.4+)
      return in_array($value, [
      $valueToCheckAgainst, $valueToCheckAgainst2, $valueToCheckAgainst3
      ]);
      
      // Using the array function (all PHP versions)
      return in_array($value, array(
      $valueToCheckAgainst, $valueToCheckAgainst2, $valueToCheckAgainst3
      ));
      

      As for why your code is not working, would it be possible to see more of the code and some sample data? From what you've described something like this should work fine (of course the conditional logic might have to change):

      $myArray = array(10, 11, 12, 13, 14, 15);
      
      $org_ids = [0, 5, 6, 14];
      
      $myNewArray = array_filter($myArray, function($value) use ($org_ids) {
      return in_array($value, $org_ids);
      });
      

      That being said, if all you want to do is check what values the $myArray array has that are also present in the $org_ids array, the array_intersect function (more information here (opens in new window/tab)) will give you the same results with less typing:

      <?php
      
      $myArray = array(10, 11, 12, 13, 14, 15,5);
      
      $org_ids = [0, 5, 6, 14];
      
      $myNewArray = array_intersect($myArray, $org_ids);
      

      After the above example has executed, the $myNewArray array would contain the values 14 and 5.

  • Kaveen
    Kaveen
    April 8, 2020 7:31 AM Reply

    Thanks a lot John. This is exactly what I was looking for. I hope you are staying safe!

Up Next

Subscribe to our newsletter