Explanation of the difference between PHP closure obtaining external variables and global keyword declaring variables

  • 2021-08-21 19:56:09
  • OfStack

Recently, when learning workerman, I frequently come into contact with callback functions. In use, I often use these two different ways to call external worker variables because of the different ways of using worker. Here, I will sort out the difference between obtaining external variables by PHP closure under 1 and declaring variables by global keywords.

Closure

Closures are a common concept that we can usually use in conjunction with callback functions to make code more concise and readable.

Closures can be copied to allow functions to use variables in the parent scope. Such as:


$global = 'hello';
$bbb = function()use($global){
  echo $global."\n";
};
$bbb();
// Output  'hello'

global keyword declaration variable

Declaring variables through global can also make the function body call variables outside the function. However, unlike use, global keyword will create a reference with the same name as the external variable, and modifying the variable within the function will also scope the external variable.


$global = 'hello';
$fun = function(){
  global $global;
  $global =' world';
  echo $global."\n";
};
$fun();
//  Output  'world'

Just create a reference with the same name, and it doesn't change the scope of the original external variable $global, which means that calling this in another function still needs to declare or use closures


$global = 'hello';
$fun = function(){
  global $global;
  $global =' world';
  echo 'a:'.$global."\n";
};
$ccc = function(){
  echo 'b:'.$global;
};
$fun()
$ccc()
/*

Output


a: world
Notice: Undefined variable: global in xxxxxxx on line xx
*/

A little bit more code change to make it easier to compare closures with global keyword declarations of variables, the two ways of accessing external variables.


<?php
$global = 'hello';
$fun = function(){
  global $global;
  $global ='world';
  echo 'a:'.$global."\n";
};
$bbb = function()use($global){
  $global = 'china';
  echo 'c:'.$global."\n";
};
$fun();
echo 'b:'.$global."\n";
$bbb();
echo 'd:'.$global;

As can be seen from the outputs of b and d, global changes the value of the external variable, but the closure mode does not.

Output:


a: world
b: world
c:china
d: world

Finally, post a classic example of using anonymous functions, closures and callback functions in official documents:


class Cart
{
  const PRICE_BUTTER = 1.00;
  const PRICE_MILK  = 3.00;
  const PRICE_EGGS  = 6.95;
  protected  $products = array();
  public function add($product, $quantity)
  {
    $this->products[$product] = $quantity;
  }
  public function getQuantity($product)
  {
    return isset($this->products[$product]) ? $this->products[$product] :
      FALSE;
  }
  public function getTotal($tax)
  {
    $total = 0.00;
    $callback =
      function ($quantity, $product) use ($tax, &$total)
      {
        $pricePerItem = constant(__CLASS__ . "::PRICE_" .
          strtoupper($product));
        $total += ($pricePerItem * $quantity) * ($tax + 1.0);
      };
    array_walk($this->products, $callback);
    return round($total, 2);
  }
}
$my_cart = new Cart;
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);
print $my_cart->getTotal(0.05) . "\n";

Summarize


Related articles: