Heim >Datenbank >MySQL-Tutorial >Detaillierte Erläuterung der Beispiele für die Verwendung von Schließungen in PHP

Detaillierte Erläuterung der Beispiele für die Verwendung von Schließungen in PHP

怪我咯
怪我咯Original
2017-07-11 15:46:321463Durchsuche

Abschluss, Anonyme Funktionen , auch bekannt als anonyme Funktionen, wurden in PHP5.3 eingeführt. Eine anonyme Funktion ist eine Funktion ohne definierten Namen, also einen Abschluss. Beachten Sie dies, um die Definition einer anonymen Funktion zu verstehen. Zum Beispiel der folgende Code (der Dateiname ist do.php)

<?php
function A() {
  return 100;
};
function B(Closure $callback)
{
  return $callback();
}
$a = B(A());
print_r($a);//输出:Fatal error: Uncaught TypeError: Argument 1 passed to B() must be an instance of Closure, integer given, called in D:\web\test\do.php on line 11 and defined in D:\web\test\do.php:6 Stack trace: #0 D:\web\test\do.php(11): B(100) #1 {main} thrown in D:\web\test\do.php on line 6
?>

A() kann hier niemals als Parameter von B verwendet werden, da A keine „anonyme“ Funktion ist

, daher sollte es wie folgt geändert werden:

<?php
$f = function () {
  return 100;
};
function B(Closure $callback)
{
  return $callback();
}
$a = B($f);
print_r($a);//输出100
<?
$func = function( $param ) {
  echo $param;
};
$func( &#39;hello word&#39; );
//输出:hello word

Abschlüsse implementieren

Anonyme Funktionen als Parameter in gewöhnlichen Funktionen übergeben und auch zurückgegeben werden können. Dies implementiert einen einfachen Abschluss. >Ich werde unten drei Beispiele geben 🎜>

Schlüsselwörter, die Abschlüsse und externe Variablen verbinden: USE

<?php
//例一
//在函数里定义一个匿名函数,并且调用它
function printStr() {
  $func = function( $str ) {
    echo $str;
  };
  $func( &#39; hello my girlfriend ! &#39; );
}
printStr();//输出 hello my girlfriend !
//例二
//在函数中把匿名函数返回,并且调用它
function getPrintStrFunc() {
  $func = function( $str ) {
    echo $str;
  };
  return $func;
}
$printStrFunc = getPrintStrFunc();
$printStrFunc( &#39; do you love me ? &#39; );//输出 do you love me ?
//例三
//把匿名函数当做参数传递,并且调用它
function callFunc( $func ) {
  $func( &#39; no!i hate you &#39; );
}
$printStrFunc = function( $str ) {
  echo $str.&#39;<br>&#39;;
};
callFunc( $printStrFunc );
//也可以直接将匿名函数进行传递。如果你了解js,这种写法可能会很熟悉
callFunc( function( $str ) {
  echo $str; //输出no!i hate you
} );
Abschlüsse können einige Variablen und Werte im Kontext des Codeblocks speichern, in dem sie sich standardmäßig befinden. Anonyme Funktionen können die Kontextvariablen des Codeblocks, in dem sie sich befinden, nicht aufrufen, sondern müssen das Schlüsselwort use

verwenden. Schauen wir uns ein anderes Beispiel an (ok, mir fehlt das Geld, ich bin vulgär):

Wie Sie sehen, ist Dollar nicht im Schlüsselwort use deklariert und kann daher in dieser anonymen Funktion nicht abgerufen werden. Daher sollten Sie bei der Entwicklung auf dieses Problem achten.

<?php
function getMoney() {
  $rmb = 1;
  $dollar = 8;
  $func = function() use ( $rmb ) {
    echo $rmb;
    echo $dollar;
  };
  $func();
}
getMoney();
//输出:1
Einige Die Leute denken vielleicht: Ist es möglich, die Kontextvariablen in einer anonymen Funktion zu ändern, aber ich habe festgestellt, dass dies nicht möglich zu sein scheint:

Nun, es stellt sich heraus, dass sich die Verwendung nur auf einen Klon davon bezieht Variable. Aber ich denke, möchten Sie die Variable vollständig referenzieren, anstatt sie zu kopieren? Wenn die anonyme Funktion an die Außenwelt zurückgegeben wird, speichert die anonyme Funktion die durch die Verwendung referenzierten Variablen, die Außenwelt kann diese Variablen jedoch nicht abrufen. Vielleicht ist es klarer

<?php
function getMoney() {
  $rmb = 1;
  $func = function() use ( $rmb ) {
    echo $rmb.&#39;<br>&#39;;
    //把$rmb的值加1
    $rmb++;
  };
  $func();
  echo $rmb;
}
getMoney();
//输出:
//1
//1
Anhand der Beschreibung werden wir das obige Beispiel weiter erläutern:

<?php
function getMoney() {
  $rmb = 1;
  $func = function() use ( &$rmb ) {
    echo $rmb.&#39;<br>&#39;;
    //把$rmb的值加1
    $rmb++;
  };
  $func();
  echo $rmb;
}
getMoney();
//输出:
//1
//2
Okay, so viel, was ist, wenn wir eine anonyme Funktion in einer Klasse aufrufen möchten? ? Direkt zur Demo gehen

A::testA() gibt eine unbenannte Funktion zurück

<?php
function getMoneyFunc() {
  $rmb = 1;
  $func = function() use ( &$rmb ) {
    echo $rmb.&#39;<br>&#39;;
    //把$rmb的值加1
    $rmb++;
  };
  return $func;
}
$getMoney = getMoneyFunc();
$getMoney();
$getMoney();
$getMoney();
//输出:
//1
//2
//3

Das Konzept der Bindung
<?php
class A {
  public static function testA() {
    return function($i) { //返回匿名函数
      return $i+100;
    };
  }
}
function B(Closure $callback)
{
  return $callback(200);
}
$a = B(A::testA());
print_r($a);//输出 300

Der Abschluss im obigen Beispiel ist nur eine anonyme Funktion. Okay, jetzt möchten wir eine Klasse mit einer anonymen Funktion angeben. Es kann auch verstanden werden, dass der Zugriffsbereich dieser anonymen Funktion nicht mehr global ist. sondern den Zugriffsbereich einer Klasse. Dann müssen wir „eine anonyme Funktion an eine Klasse“ binden. Im obigen Beispiel hat die anonyme Funktion f ein unerklärliches this, und das Schlüsselwort this erklärt dies . Anonyme Funktionen müssen in der Klasse gebunden werden.

Nach der Bindung ist es so, als ob es eine solche Funktion in A gäbe, aber unabhängig davon, ob die Funktion öffentlich oder privat ist, gibt der letzte Parameter der Bindung die Funktion an . Aufrufbarer Bereich.

Sie haben bindTo oben gesehen, werfen wir einen Blick auf die Einführung auf der offiziellen Website

<?php
class A {
  public $base = 100;
}
class B {
  private $base = 1000;
}
$f = function () {
  return $this->base + 3;
};
$a = Closure::bind($f, new A);
print_r($a());//输出 103
echo PHP_EOL;
$b = Closure::bind($f, new B , &#39;B&#39;);
print_r($b());//输出1003
Closure::bind – Kopieren Sie einen Abschluss und binden Sie das angegebene $this-Objekt und den angegebenen Klassenbereich .

Beschreibung

public static Closure Closure::bind ( Closure $closure , object $newthis [, Mixed $newscope = 'static' ] )

Diese Methode ist

Closure: Statische Version von :bindTo
(PHP 5 >= 5.4.0, PHP 7)
(). Weitere Informationen finden Sie in der Dokumentation.

Parameter

Abschluss


Eine anonyme Funktion, die gebunden werden muss. newthis

erfordert ein Objekt, das an eine anonyme Funktion gebunden ist, oder NULL erstellt einen ungebundenen Abschluss.

newscope

Der Klassenbereich, den Sie an den Abschluss binden möchten, oder „statisch“ bedeutet keine Änderung. Wenn ein Objekt übergeben wird, wird der Typname des Objekts verwendet. Der Klassenbereich wird verwendet, um die Sichtbarkeit privater, geschützter Methoden des $this-Objekts innerhalb des Abschlusses zu bestimmen. (Hinweis: Sie können den Klassennamen oder eine Instanz der Klasse übergeben. Der Standardwert ist „statisch“, was bedeutet, dass keine Änderung erfolgt.)

Rückgabewert:

Einen neuen Abschluss zurückgeben Objekt oder bei Fehler Rückgabe FALSE

Schauen wir uns ein Beispiel an, um unser Verständnis zu vertiefen:

Schauen wir uns eine andere Demo an:

Durch In den obigen Beispielen ist es tatsächlich nicht schwer, die anonyme Bindung zu verstehen.... Wir sehen uns eine erweiterte Demo an (Einführung von Merkmalsfunktionen)
<?php
class A {
  private static $sfoo = 1;
  private $ifoo = 2;
}
$cl1 = static function() {
  return A::$sfoo;
};
$cl2 = function() {
  return $this->ifoo;
};
$bcl1 = Closure::bind($cl1, null, &#39;A&#39;);
$bcl2 = Closure::bind($cl2, new A(), &#39;A&#39;);
echo $bcl1(), "\n";//输出 1
echo $bcl2(), "\n";//输出 2

Zum Beispiel verwenden wir jetzt die aktuelle Einkaufsumgebung
<?php
class A {
  public $base = 100;
}
class B {
  private $base = 1000;
}
class C {
  private static $base = 10000;
}
$f = function () {
  return $this->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 , &#39;B&#39;);
print_r($b());//这里输出1003,绑定到B类
echo PHP_EOL;
$c = $sf->bindTo(null, &#39;C&#39;); //注意这里:使用变量#sf绑定到C类,默认第一个参数为null
print_r($c());//这里输出10003

Zusätzlicher Hinweis: Abschlüsse können die USE-Taste verwenden, um externe Variablen zu verbinden.
<?php
/**
 * 复制一个闭包,绑定指定的$this对象和类作用域。
 *
 * @author fantasy
 */
class Animal {
  private static $cat = "加菲猫";
  private $dog = "汪汪队";
  public $pig = "猪猪侠";
}
/*
 * 获取Animal类静态私有成员属性
 */
$cat = static function() {
  return Animal::$cat;
};
/*
 * 获取Animal实例私有成员属性
 */
$dog = function() {
  return $this->dog;
};
/*
 * 获取Animal实例公有成员属性
 */
$pig = function() {
  return $this->pig;
};
$bindCat = Closure::bind($cat, null, new Animal());// 给闭包绑定了Animal实例的作用域,但未给闭包绑定$this对象
$bindDog = Closure::bind($dog, new Animal(), &#39;Animal&#39;);// 给闭包绑定了Animal类的作用域,同时将Animal实例对象作为$this对象绑定给闭包
$bindPig = Closure::bind($pig, new Animal());// 将Animal实例对象作为$this对象绑定给闭包,保留闭包原有作用域
echo $bindCat(),&#39;<br>&#39;;// 输出:加菲猫,根据绑定规则,允许闭包通过作用域限定操作符获取Animal类静态私有成员属性
echo $bindDog(),&#39;<br>&#39;;// 输出:汪汪队, 根据绑定规则,允许闭包通过绑定的$this对象(Animal实例对象)获取Animal实例私有成员属性
echo $bindPig(),&#39;<br>&#39;;// 输出:猪猪侠, 根据绑定规则,允许闭包通过绑定的$this对象获取Animal实例公有成员属性

Zusammenfassung: Die Eigenschaften von PHP-Abschlüssen können tatsächlich genutzt werden, um mit CLASS ähnliche oder sogar leistungsfähigere Funktionen zu erreichen, ganz zu schweigen von den Abschlüssen von js. Ich kann nur hoffen, dass PHP sie in Zukunft verbessern wird
<?php
/**
 * 给类动态添加新方法
 *
 * @author fantasy
 */
trait DynamicTrait {
  /**
   * 自动调用类中存在的方法
   */
  public function call($name, $args) {
    if(is_callable($this->$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 = &#39;汪汪队&#39;;
}
$animal = new Animal;
// 往动物类实例中添加一个方法获取实例的私有属性$dog
$animal->getdog = function() {
  return $this->dog;
};
echo $animal->getdog();//输出 汪汪队
Verbesserungen bei der Schließungsunterstützung

. Allerdings sind anonyme Funktionen immer noch sehr nützlich. Wenn Sie beispielsweise Funktionen wie preg_replace_callback verwenden, ist es nicht erforderlich, die

Callback-Funktion
<?php
/**
 * 一个基本的购物车,包括一些已经添加的商品和每种商品的数量
 *
 * @author fantasy
 */
class Cart {
  // 定义商品价格
  const PRICE_BUTTER = 10.00;
  const PRICE_MILK  = 30.33;
  const PRICE_EGGS  = 80.88; 
  protected  $products = array();
  /**
   * 添加商品和数量
   *
   * @access public
   * @param string 商品名称
   * @param string 商品数量
   */
  public function add($item, $quantity) {
    $this->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(&#39;butter&#39;, 10);
$my_cart->add(&#39;milk&#39;, 3);
$my_cart->add(&#39;eggs&#39;, 12);
// 打出出总价格,其中有 3% 的销售税.
echo $my_cart->getTotal(0.03);//输出 1196.4
extern zu deklarieren. Durch die richtige Verwendung von Abschlüssen kann der Code prägnanter und verfeinert werden.

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Beispiele für die Verwendung von Schließungen in PHP. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn