Test HTTP Requests Tools Blog Learn Quizzes Smile API Log In / Sign Up
Test HTTP Requests Tools Blog Learn Quizzes Smile API Log In / Sign Up
« Return to the tutorials listFeatured in PHP Weekly
We have updated the website and our policies to make sure your privacy rights and security are respected.
Click here to learn more about the way our website handles your data.

Remove this message.

Basic usage of closures in PHP

Daniel Gheorghe Difficulty: 30 / 50 Tweet
php-closures

Closures have been introduced in PHP 5.3 and their most important use is for callback functions. Basically a closure in PHP is a function that can be created without a specified name - an anonymous function. Here's a closure function created as the second parameter of array_walk(). By specifying the $v parameter as a reference one can modify each value in the original array through the closure function.

  
    <?php
      $array = array('Ruby', 'PHP', 'JavaScript', 'HTML');
      array_walk($array, function(&$v, $k) {
        $v = $v . ' - Programming Language';
      });
      print_r($array);
  

Assigning a closure as the value of a variable

You can define a closure as the value of a variable with a normal assignment. For example, the snippet below will print out 'I am a closure'.

  
    <?php
    $var = function() {
      return 'I am a ' . func_get_arg(0);
    };
    print_r($var('Closure'));
  

Don't forget to end the assignment with a semicolon just like you would do with any variable definition ... I always forget so I thought it would help if I mentioned this :).

Be careful with the scope

One of the most confusing aspects for these anonymous functions in PHP is related to how closures can make use of variables from their immediate parent scope (not necessarily the global scope). This is done with the use language construct so that the syntax looks like this: function() use ($variable) { /* code */ }.

In the example below, the closure will use / inherit the value of $param from its parent scope which is the scope of the sayHello() function, NOT the global scope and therefor the script will output Hi, I am Michael!.

  
    <?php
    $param  = 'John!';

    function sayHello()
    {
      $param = 'Michael!';
      $func  = function() use ($param)
      {
        echo 'Hi, I am ' . $param;
      };
      $func();
    }

    sayHello();
  

If we were to modify the value of $param inside the closure this would not affect it's value inside the parent scope unless we would 'use a reference'. In the two examples below, one with $param as a reference and one as a normal (copied) variable the results are different.

This prints 'I am Michael!' because $param is not modified in its parent scope. In other words, the only place where $param='Dave!' is inside the closure.

  
    <?php
    $param  = 'John!';

    function sayHello()
    {
      $param = 'Michael!';
      $func  = function() use ($param)
      {
        $param = 'Dave!';
      };
      $func();
      echo 'I am ' . $param; // prints I am Michael!
    }
    sayHello();
  

The code below will print 'I am Dave!' because $param is 'used' as a reference.

  
    <?php
    $param  = 'John!';

    function sayHello()
    {
      $param = 'Michael!';
      $func  = function() use (&$param)
      {
        $param = 'Dave!';
      };
      $func();
      echo 'I am ' . $param; // prints I am Dave!
    }
    sayHello();
  

Update: January 7th 2020 - Arrow functions starting with PHP 7.4

Starting with version 7.4 PHP has the ability to interpret "arrow functions". Besides the obvious advatage of being shorter and more readable than classic anonymous functions, arrow functions can access variables from the parent scope through a technique called "implicit by-value scope binding"

Below there's a comparison between how a clasic closure behaves compared with a short closure.

  
        <?php
            //classic closure 
            $n = "Mike";
            $calc = function() {
                return "Hello " . $n;
            }
            $calc();  // undefined variable $n
        ?>
        <?php
            //short closure
            $calc = fn() => "Hello " . $n;
            $calc(); //returns Hello Mike
        ?>
    

A few gotchas:

Arrow functions can only have one expression - the return statement (as opposed to JavaScript)

The outer scope variables are accessible by value only so there's no way of modify them

comments powered by Disqus