Home  >  Article  >  Backend Development  >  Summarize the example tutorial of closure in php

Summarize the example tutorial of closure in php

零下一度
零下一度Original
2017-06-15 14:05:521069browse

This article mainly introduces the detailed usage of closure in php. Friends who need it can refer to it

Closure, anonymous function, was introduced in php5.3, also known as Anonymous functions. The literal meaning is a function without a defined name. For example, the following code (the file name is do.php)


A() here can never be used as a parameter of B, because A is not "anonymous" function.

So it should be changed to this:


Implement closure

Will Anonymous functions are passed in as parameters in ordinary functions and can also be returned. This implements a simple closure.

I will give three examples below:


';
};
callFunc( $printStrFunc );
//也可以直接将匿名函数进行传递。如果你了解js,这种写法可能会很熟悉
callFunc( function( $str ) {
  echo $str; //输出no!i hate you
} );

Keywords to connect closures and external variables: USE

Closures can be saved Some variables and values ​​in the context of the code block. By default in PHP, anonymous functions cannot call context variables in the code block where they are located, but need to use the use keyword.

Let’s look at another example (ok, I’m short of money, I’m vulgar):


As you can see, dollar is not in the use keyword declaration, it cannot be obtained in this anonymous function, so you should pay attention to this issue during development.

Some people may wonder whether it is possible to change context variables in an anonymous function, but I found that it seems not possible:


';
    //把$rmb的值加1
    $rmb++;
  };
  $func();
  echo $rmb;
}
getMoney();
//输出:
//1
//1

Well, it turns out What use refers to is nothing more than a clone of the variable. But what if I want to completely quote the variable instead of copying it? To achieve this effect, actually add an & symbol before the variable:


';
    //把$rmb的值加1
    $rmb++;
  };
  $func();
  echo $rmb;
}
getMoney();
//输出:
//1
//2

Okay, like this Anonymous functions can reference context variables. If the anonymous function is returned to the outside world, the anonymous function will save the variables referenced by use, but the outside world will not be able to obtain these variables. In this way, the concept of 'closure' may be clearer.

According to the description, let’s change the above example:


';
    //把$rmb的值加1
    $rmb++;
  };
  return $func;
}
$getMoney = getMoneyFunc();
$getMoney();
$getMoney();
$getMoney();
//输出:
//1
//2
//3

Okay, so much, then if we want to call an anonymous object in a class What about functions? Go directly to the demo


where A::testA() returns an unnamed funciton.

The concept of binding

The Closure in the above example is just a global anonymous function. Okay, now we want to specify a class There is an anonymous function. It can also be understood that the access scope of this anonymous function is no longer global, but the access scope of a class.

Then we need to bind "an anonymous function to a class".


base + 3;
};
$a = Closure::bind($f, new A);
print_r($a());//输出 103
echo PHP_EOL;
$b = Closure::bind($f, new B , 'B');
print_r($b());//输出1003

In the above example, the anonymous function f has an inexplicable this. This keyword means that this anonymous function needs to be bound to the class. .

After binding, it is as if there is such a function in A, but whether this function is public or private, the last parameter of bind indicates the callable scope of this function.

You have seen bindTo above, let’s take a look at the introduction on the official website


(PHP 5 >= 5.4.0, PHP 7)

Closure::bind — Copy a closure and bind the specified $this Object and class scope.

Description

public static Closure Closure::bind ( Closure $closure , object $newthis [, mixed $newscope = 'static' ] )
This method is Closure::bindTo( ) static version. Check out its documentation for more information.

Parameters

closure

Anonymous function that needs to be bound.

newthis

Requires an object bound to an anonymous function, or NULL to create an unbound closure.

newscope

The class scope you want to bind to the closure, or 'static' means no change. If an object is passed in, the type name of the object is used. Class scope is used to determine the visibility of private, protected methods of the $this object within the closure. (Note: You can pass in the class name or an instance of the class. The default value is 'static', which means no change.)

Return value:

Return a new Closure object or on failure Return FALSE


ifoo;
};
$bcl1 = Closure::bind($cl1, null, 'A');
$bcl2 = Closure::bind($cl2, new A(), 'A');
echo $bcl1(), "\n";//输出 1
echo $bcl2(), "\n";//输出 2

Let’s look at an example to deepen our understanding:


base + 3;
};
$sf = static function() {
  return self::$base + 3;
};
$a = Closure::bind($f, new A);
print_r($a());//这里输出103,绑定到A类
echo PHP_EOL;
$b = Closure::bind($f, new B , 'B');
print_r($b());//这里输出1003,绑定到B类
echo PHP_EOL;
$c = $sf->bindTo(null, 'C'); //注意这里:使用变量#sf绑定到C类,默认第一个参数为null
print_r($c());//这里输出10003

Let’s look at another demo:


dog;
};
/*
 * 获取Animal实例公有成员属性
 */
$pig = function() {
  return $this->pig;
};
$bindCat = Closure::bind($cat, null, new Animal());// 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象
$bindDog = Closure::bind($dog, new Animal(), 'Animal');// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包
$bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域
echo $bindCat(),'
';// 输出:加菲猫,根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性 echo $bindDog(),'
';// 输出:汪汪队, 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性 echo $bindPig(),'
';// 输出:猪猪侠, 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性

Through the above examples, it is actually not difficult to understand anonymous binding.... We are looking at an extended demo (introducing trait features)


$name)){
      return call_user_func($this->$name, $args);
    }else{
      throw new \RuntimeException("Method {$name} does not exist");
    }
  }
  /**
   * 添加方法
   */
  public function __set($name, $value) {
    $this->$name = is_callable($value)?
      $value->bindTo($this, $this):
      $value;
  }
}
/**
 * 只带属性不带方法动物类
 *
 * @author fantasy
 */
class Animal {
  use DynamicTrait;
  private $dog = '汪汪队';
}
$animal = new Animal;
// 往动物类实例中添加一个方法获取实例的私有属性$dog
$animal->getdog = function() {
  return $this->dog;
};
echo $animal->getdog();//输出 汪汪队

For example, now we use the current shopping environment


products[$item] = $quantity;
  }
  /**
   * 获取单项商品数量
   *
   * @access public
   * @param string 商品名称
   */
  public function getQuantity($item) {
    return isset($this->products[$item]) ? $this->products[$item] : FALSE;
  }
  /**
   * 获取总价
   *
   * @access public
   * @param string 税率
   */
  public function getTotal($tax) {
    $total = 0.00;
    $callback = function ($quantity, $item) use ($tax, &$total) {
      $pricePerItem = constant(__CLASS__ . "::PRICE_" . strtoupper($item)); //调用以上对应的常量
      $total += ($pricePerItem * $quantity) * ($tax + 1.0);
    };
    array_walk($this->products, $callback);
    return round($total, 2);
  }
}
$my_cart = new Cart;
// 往购物车里添加商品及对应数量
$my_cart->add('butter', 10);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 12);
// 打出出总价格,其中有 3% 的销售税.
echo $my_cart->getTotal(0.03);//输出 1196.4

Additional explanation: Closures can use the USE key to connect external variables.

Summary: The characteristics of PHP closures can actually achieve similar or even more powerful functions using CLASS, let alone the closures of js. We can only hope that PHP will support closures in the future. improvement of. However, anonymous functions are still quite useful. For example, when using functions such as preg_replace_callback, you don't need to declare a callback function externally. Proper use of closures can make code more concise and refined.

The above is the detailed content of Summarize the example tutorial of closure in php. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn