Home » Code » What are PHP Lambdas and Closures?

What are PHP Lambdas and Closures?

Posted by on March 25th, 2013

What are PHP Lambdas and Closures
Lambdas and Closures are relatively new additions to PHP after shipping with version 5.3. Both offer some new functionality and the ability to refactor old code to be cleaner and more intuitive. However, I think many developers are unaware of Lambdas and Closures or confused about what they actually do.

In this post I will be explaining Lambdas and Closures, give you some example code to show their usage and give you a real life example of them in action to show you their prevalence in modern PHP.

What is a Lambda?

A Lambda is an anonymous function that can be assigned to a variable or passed to another function as an argument. If you are familiar with other programming languages like Javascript or Ruby, you will be very familiar with anonymous functions.

Anonymous functions

An anonymous function is simply a function with no name.

For example, to create a regular function, you might write something like this:

// Regular function
function greeting () {
	return "Hello world";
}

You can then simply call this function like this:

echo greeting();
// Returns "Hello world"

An anonymous function has no name so you would define it like this:

// Anonymous function
function () {
	return "Hello world";
}

Using Lambdas

Because the function has no name, you can’t call it like a regular function. Instead you must either assign it to a variable or pass it to another function as an argument.

// Anonymous function
// assigned to variable
$greeting = function () {
  return "Hello world";
}

// Call function
echo $greeting();
// Returns "Hello world"

To so use the anonymous function, we assign it to a variable and then call that variable as a function.

You could also pass the function to another function, like this:

// Pass Lambda to function
function shout ($message){
	echo $message();
}

// Call function
shout(function(){
	return "Hello world";
});

Why would you want to use a Lambda?

Lambdas are useful because they are throw away functions that you can use once. Often, you will need a function to do a job, but it doesn’t make sense to have it within the global scope or to even make it available as part of your code. Instead of having a function used once and then left lying around, you can use a Lambda instead.

Of course, you have been able to use the create_function function in PHP for a while now. This basically does the same job.

// Use create_function
$greeting = create_function('', 'echo "Hello World!";');

// Call function
$greeting();

What is a Closure?

A Closure is essentially the same as a Lambda apart from it can access variables outside the scope that it was created.

For example:

// Create a user
$user = "Philip";

// Create a Closure
$greeting = function() use ($user) {
  echo "Hello $user";
};

// Greet the user
$greeting(); // Returns "Hello Philip"

As you can see above, the Closure is able to access the $user variable. because it was declared in the use clause of the Closure function definition.

If you were to alter the $user variable within the Closure, it would not effect the original variable. To update the original variable, we can append an ampersand. An ampersand before a variable means this is a reference and so the original variable is also updated.

For example:

// Set counter
$i = 0;
// Increase counter within the scope
// of the function
$closure = function () use ($i){ $i++; };
// Run the function
$closure();
// The global count hasn't changed
echo $i; // Returns 0

// Reset count
$i = 0;
// Increase counter within the scope
// of the function but pass it as a reference
$closure = function () use (&$i){ $i++; };
// Run the function
$closure();
// The global count has increased
echo $i; // Returns 1

Closures are also useful when using PHP functions that accept a callback function like array_map, array_filter, array_reduce or array_walk.

The array_walk function takes an array and runs it through the callback function.

// An array of names
$users = array("John", "Jane", "Sally", "Philip");

// Pass the array to array_walk
array_walk($users, function ($name) {
	echo "Hello $name<br>";
});
// Returns
// -> Hello John
// -> Hello Jane
// -> ..

Again, you can access variables outside the scope of the Closure by using the use clause:

// Set a multiplier
$multiplier = 3;

// Create a list of numbers
$numbers = array(1,2,3,4);

// Use array_walk to iterate
// through the list and multiply
array_walk($numbers, function($number) use($multiplier){
	echo $number * $multiplier;
});

In the example above, it probably wouldn’t make sense to create a function to just multiply two numbers together. If you were to create function to do a job like this, then come back to the code a while later you will probably be thinking why did you bother create a globally accessible function only to be used once? By using a Closure as the callback, we can use the function once and then forget about it.

Real life usage

So we’ve established that Lambdas and Closures are anonymous functions that can be used as throw away bits of functionality that don’t pollute the global namespace and are good to use as part of a callback.

A popular example of the use of these types of functions is in routing requests within modern frameworks. Laravel for example, allows you to do the following:

Route::get('user/(:any)', function($name){
  return "Hello " . $name;
});

The code above simply matches a URL like /user/philip and returns a greeting.

This is a very basic example, but it highlights how a Closure can be utilised in a very useful situation.

Conclusion

So hopefully that was a good explanation of Lambdas and Closures.

Lambdas and Closures seem like two very deep Computer Science terms if you are a newbie programmer. However, it’s actually not that complicated at all. Both Lambdas and Closures are simply anonymous functions that are useful for one offs or where it doesn’t make sense to define a function.

Lambdas and Closures are fairly new to PHP and they don’t follow exactly the same usage as in other languages. If you are at all familiar with Javascript, you will see anonymous functions used a lot. In particular, you will see a lot of good examples in jQuery. Once you can recognise the pattern, it makes reading code a lot easier because you not only understand what is going on, but also understand why it was written like that in the first place and what the developer was trying to achieve through her decisions.

Philip Brown

Hey, I'm Philip Brown, a designer and developer from Durham, England. I create websites and web based applications from the ground up. In 2011 I founded a company called Yellow Flag. If you want to find out more about me, you can follow me on Twitter or Google Plus.

  • flackjap

    I like how you addressed a developer with female gender :))

    • Thank you :)

    • jgnasser

      I couldn’t help but notice that!

  • Tournas Dimitrios

    Closures were introduced in PHP 5.3, but 5.4 enhanced how they interact with objects (closure object binding) .

    And example will explain my thoughts :
    // Run it with php5.4
    class Foo {
    private $color;
    function __construct($color) {
    $this->color = $color;
    }
    public function getProperty() {
    return function() {
    echo ucfirst($this->color); };
    }
    }// end of Class Foo
    $a = new Foo(‘red’);
    $func = $a->getProperty();
    $func(); // Outputs: Red (only on php5.4)

    // Run it with php5.3
    Fatal error: Using $this when not in object context in /tmp/closuretest.php on line 12

    // A trick to bypass the error in php5.3 :
    class Foo {
    public $color;
    function __construct($color) {
    $this->color = $color;
    }
    public function getProperty() {
    $self = $this ;
    return function() use ($self) {
    echo ucfirst($self->color); };
    }
    }// end of Class Foo
    $a = new Foo(‘red’);
    $func = $a->getProperty();
    $func(); // Outputs: Red (on php5.3 and php5.4)

    Notice that we had to change the visibility of Foo’s $color attribute , which might not be a good choice in some circumstances .

    A couple concepts worth mentioning are :
    ***By default, closures in PHP use early-binding – which means that variables inside the closure will have the value they had when the closure was defined . This can be over-ridden though , by using references (&) or re-bound the closure (which lead to re-assign the value) .
    ***Opcode cachers can “cache” closures . While create_function() is created at “run-time” , Closures are created at “compile-time” . We could “cache” closures to boost the performance of our code .

    • Thank you Tournas, that’s very interesting :)

  • Joeri

    Love these pages…
    ( found a typo: .. A Lambda is an anonymous function that is can be assigned to a variable or … ) one ‘is’ too many?

  • Thank you for this article. Its comprehensive, easy to understand and has enough examples.

  • bumpasaurusx

    Great article, Been trying to grasp this for a spell and this really helped get it through my skull. Thanks!

  • Shashi Kumar

    really nice topic you have shared for us, i am a new programmer in php and laravel,is nice to me ..if any reading for new bie in php and larravel pls send or lnk me..
    thank you very much..

    • Thank you :)

      Yeah, I have lots http://culttt.com/tag/php :D

      • Shashi Kumar

        Thank you very much . You have any examples of sentry package using with some demo examples with users permission. :)

        • No I’ve never used Sentry.

          • Shashi Kumar

            It’s ok thankyou very much for replay.

  • Lauren Clark

    Thanks for this :)

    • No problem Lauren, glad you found it useful :)

  • Jan

    Great article, very helpful.. :)

  • jgnasser

    Philip, you have a talent right there. Its hard to explain these concepts in a way that (especially) people new to programming can understand. Thanks for a very clear explanation.

  • vince

    I really love your site – I wish i knew how you do it when it’s not a paid job – man you must work 23 hours a day !

    • haha, thanks Vince! It feels like I work 23 hours a day sometimes :(

  • isomoar

    Very simple and clear explanation, thank you for this article!

  • Md.Atiquzzaman Soikat

    Thanks a lot man for this awesome simple to understand tutorial. Highly appreciated.

  • rakesh

    Thank you very much….Philip….the resource turns to be very helpful for me…surely it has saved me time…

  • Awesome article @philip_brown:disqus!

    There are some typos in the code:

    (1) In **Using Lambdas** section in the 2nd block of code in line 3 should be `echo $message();`.

    (2) In **Why would you want to use a Lambda?** section the use of `create_function` function is wrong. It should looks like `$greeting = create_function(”, ‘echo “Hello World!”;’);`.

    (3) In **What is a Closure?** section in the 4th block of code in line 5 should be `$numbers = (1,2,3,4);`.

    Thanks!

  • Pingback: Creating a PHP Shopping Basket Part 2 - Working with Collections | Culttt()

  • Ahmad Mayahi

    Dude, that was amazing. :-)

    • Thank you Ahmad, glad you found it useful! :D

  • Aug Hki

    excellent!

  • Pratik Joshi

    Thanks for sharing budddddddddddddddddddy! :)