Heim  >  Artikel  >  Backend-Entwicklung  >  Analysieren Sie die Funktionen von PHP-Verschlüssen und Clourse-Klassenmethoden

Analysieren Sie die Funktionen von PHP-Verschlüssen und Clourse-Klassenmethoden

藏色散人
藏色散人nach vorne
2022-02-05 04:00:324646Durchsuche

PHP Clourse (Abschlussklasse) Eine kurze Analyse

0x00 Vorwort

Ein Abschluss bezieht sich auf eine Funktion, die den umgebenden Zustand bei ihrer Erstellung kapselt. Auch wenn die Umgebung, in der sich der Verschluss befindet, nicht mehr existiert, ist der im Verschluss eingekapselte Zustand weiterhin vorhanden.

Alle Abschlüsse in PHP sind Objekte, die von der Clourse-Klasse instanziiert werden, was bedeutet, dass sich Abschlüsse nicht von anderen PHP-Objekten unterscheiden. Ein Objekt muss über eigene Methoden und Eigenschaften verfügen. In diesem Artikel werden die grundlegende Verwendung von Abschlüssen in PHP und die Rolle der Clourse-Klassenmethode zusammengefasst. [Empfohlen: PHP-Video-Tutorial]

0x01 Grundlegende Verwendung von Abschlüssen

Werfen wir einen Blick auf die grundlegendste Verwendung von Abschlüssen:

<?php
$hello = function ($word) {
    return &#39;hello &#39; . $word;
};
echo $hello(&#39;world&#39;);
// 输出 hello world

Hey, das intuitivste Gefühl dieses Codes besteht darin, ihm eine Funktion zuzuweisen $hello-Variable und rufen Sie sie dann direkt über $hello auf. Dieser Abschluss erbt jedoch keine Variablen vom übergeordneten Bereich (d. h. er kapselt den umgebenden Zustand). Wir können Variablen vom übergeordneten Bereich des Abschlusses über das Schlüsselwort use erben. Beispiele sind wie folgt:

<?php
$name = &#39;panda&#39;;
$hello = function () use ($name) {
    return &#39;hello &#39; . $name;
};
echo $hello();
// 输出 hello panda

Ab PHP 7.1 kann use keine solchen Variablen übergeben: superglobals, $this oder denselben Namen als Parameter haben.

Außerdem werden bei Verwendung des Schlüsselworts use die Variablen des übergeordneten Bereichs als Wert an den Abschluss übergeben. Das heißt, sobald der Abschluss erstellt wurde, hat dies keinen Einfluss auf den an den Abschluss übergebenen Wert, selbst wenn die externen Variablen geändert werden (d. h. selbst wenn die Umgebung, in der sich der Abschluss befindet, nicht mehr existiert, ist der Zustand darin eingekapselt die Schließung besteht noch). Ein Beispiel lautet wie folgt:

<?php
$name = &#39;panda&#39;;
$hello = function () use ($name) {
    return &#39;hello &#39; . $name;
};
$name = &#39;cat&#39;;
echo $hello();
// 输出 hello panda

Durch die Übergabe eines Verweises auf eine Variable kann der Abschluss den Wert einer externen Variablen ändern. Ein Beispiel lautet wie folgt:

<?php
$name = &#39;panda&#39;;
$changeName = function () use (&$name) {
    $name = &#39;cat&#39;;
};
$changeName();
echo $name;
// 输出 cat

Hinweis: Bei der Übergabe eines Objekts in PHP ist die Standardeinstellung „pass“. Es wird als Referenz verwendet, daher ist beim Betrieb des übergebenen Objekts innerhalb des Verschlusses besondere Aufmerksamkeit erforderlich. Ein Beispiel lautet wie folgt:

<?php
class Dog {
    public $name = &#39;Wang Cai&#39;;
}
$dog = new Dog();
$changeName = function () use ($dog) {
    $dog->name = &#39;Lai Fu&#39;;
};
$changeName();
echo $dog->name;
// 输出 Lai Fu

0x02 Abschlussklasse

Beweisen Sie, dass der Abschluss nur ein Objekt der Abschlussklasse ist.

<?php
$clourse = function () {
    echo &#39;hello clourse&#39;;
};
if (is_object($clourse)) {
    echo get_class($clourse);
}
// 输出 Closure

Der obige Code gibt „Closure“ aus und beweist, dass der Abschluss nur ein gewöhnliches Objekt der Abschlussklasse ist.

Zusammenfassung der Clourse-Klasse

Die relevanten Informationen zur Abschlussklasse finden Sie im offiziellen PHP-Handbuch. Das Folgende ist die Zusammenfassung der Clourse-Klasse, die ich in der lokalen Dokumentation von PhpStorm gesehen habe.

/**
 * Class used to represent anonymous functions.
 * <p>Anonymous functions, implemented in PHP 5.3, yield objects of this type.
 * This fact used to be considered an implementation detail, but it can now be relied upon.
 * Starting with PHP 5.4, this class has methods that allow further control of the anonymous function after it has been created.
 * <p>Besides the methods listed here, this class also has an __invoke method.
 * This is for consistency with other classes that implement calling magic, as this method is not used for calling the function.
 * @link http://www.php.net/manual/en/class.closure.php
 */
final class Closure {
    /**
     * This method exists only to disallow instantiation of the Closure class.
     * Objects of this class are created in the fashion described on the anonymous functions page.
     * @link http://www.php.net/manual/en/closure.construct.php
     */
    private function __construct() { }
    /**
     * This is for consistency with other classes that implement calling magic,
     * as this method is not used for calling the function.
     * @param mixed $_ [optional]
     * @return mixed
     * @link http://www.php.net/manual/en/class.closure.php
     */
    public function __invoke(...$_) { }
    /**
     * Duplicates the closure with a new bound object and class scope
     * @link http://www.php.net/manual/en/closure.bindto.php
     * @param object $newthis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound.
     * @param mixed $newscope The class scope to which associate the closure is to be associated, or &#39;static&#39; to keep the current one.
     * If an object is given, the type of the object will be used instead.
     * This determines the visibility of protected and private methods of the bound object.
     * @return Closure Returns the newly created Closure object or FALSE on failure
     */
    function bindTo($newthis, $newscope = &#39;static&#39;) { }
    /**
     * This method is a static version of Closure::bindTo().
     * See the documentation of that method for more information.
     * @static
     * @link http://www.php.net/manual/en/closure.bind.php
     * @param Closure $closure The anonymous functions to bind.
     * @param object $newthis The object to which the given anonymous function should be bound, or NULL for the closure to be unbound.
     * @param mixed $newscope The class scope to which associate the closure is to be associated, or &#39;static&#39; to keep the current one.
     * If an object is given, the type of the object will be used instead.
     * This determines the visibility of protected and private methods of the bound object.
     * @return Closure Returns the newly created Closure object or FALSE on failure
     */
    static function bind(Closure $closure, $newthis, $newscope = &#39;static&#39;) { }
    /**
     * Temporarily binds the closure to newthis, and calls it with any given parameters.
     * @link http://php.net/manual/en/closure.call.php
     * @param object $newThis The object to bind the closure to for the duration of the call.
     * @param mixed $parameters [optional] Zero or more parameters, which will be given as parameters to the closure.
     * @return mixed
     * @since 7.0
     */
    function call ($newThis, ...$parameters) {}
    
    /**
     * @param callable $callable
     * @return Closure
     * @since 7.1
     */
    public static function fromCallable (callable $callable) {}
}

Erstens ist die Clourse-Klasse eine letzte Klasse, was bedeutet, dass sie nicht vererbt werden kann. Zweitens ist ihr Konstruktor __construct auf privat gesetzt, was bedeutet, dass das Abschlussobjekt nicht über das neue Schlüsselwort instanziiert werden kann Stellen Sie sicher, dass der Abschluss nur durch die Syntaxfunktion (...) use(...) {...} instanziiert werden kann.

Warum können Abschlüsse als Funktionen ausgeführt werden?

Aus der obigen Klassenzusammenfassung können wir ersehen, dass die Clourse-Klasse die Methode __invoke implementiert. Die Methode wird im offiziellen PHP-Handbuch wie folgt erklärt:

Beim Versuch, ein Objekt durch Aufrufen einer Funktion aufzurufen, wird die Methode __invoke() verwendet. Die Methode wird automatisch aufgerufen.

Deshalb können Abschlüsse als Funktionen ausgeführt werden.

Binden Sie das angegebene $this-Objekt und den angegebenen Klassenbereich.

In Frameworks, die die Verwendung von Closing-Routing zulassen (z. B. Slim), können wir die folgende Schrift sehen:

$app->get(&#39;/test&#39;, function () {
    echo $this->request->getMethod();
});

Kann $ tatsächlich in einem Closing this verwendet werden? Auf welches Objekt zeigt dieses $this?

Die Funktion, $this an den Klassenbereich zu binden, kann über die Methoden bindTo und bind erreicht werden. Das Beispiel lautet wie folgt:

<?php
class Pandas {
    public $num = 1;
}
$pandas = new Pandas();
$add = function () {
    echo ++$this->num . PHP_EOL;
};
$newAdd1 = $add->bindTo($pandas);
$newAdd1();
// 输出 2
$newAdd2 = Closure::bind($add, $pandas);
$newAdd2();
// 输出 3

Das obige Beispiel bindet das angegebene Objekt an das $this des Abschlusses, wir tun dies jedoch nicht Geben Sie den Klassenbereich an. Wenn Sie also die Eigenschaft $num der Klasse Pandas in protected oder private umschreiben, wird ein schwerwiegender Fehler ausgegeben!

Fatal error: Uncaught Error: Cannot access protected property Pandas::$num

Wenn wir auf nicht öffentliche Eigenschaften oder Methoden des gebundenen Objekts zugreifen müssen, müssen wir den Klassenbereich angeben. Das Beispiel sieht wie folgt aus:

<?php
class Pandas {
    protected $num = 1;
}
$pandas = new Pandas();
$add = function () {
    echo ++$this->num . PHP_EOL;
};
$newAdd1 = $add->bindTo($pandas, $pandas);
$newAdd1();
// 输出 2
$newAdd2 = Closure::bind($add, $pandas, &#39;Pandas&#39;);
$newAdd2();
// 输出 3

Hier sehen wir, dass sowohl die bindTo- als auch die bind-Methode den $newscope angeben Der Parameter $newscope ist standardmäßig statisch. Das heißt, der Klassenbereich wird nicht geändert. Der Parameter $newscope akzeptiert einen Klassennamen oder ein Objekt und ändert den Klassenbereich des Abschlusses in den angegebenen Klassenbereich. Zu diesem Zeitpunkt kann der Abschluss auf die Eigenschaft $num der Pandas-Klasse zugreifen.

Binden Sie $diesen Objekt- und Klassenbereich gleichzeitig und führen Sie ihn aus (PHP7).

bindTo- und bind-Methoden müssen den ursprünglichen Abschluss kopieren und den neuen Abschluss jedes Mal zurückgeben, wenn ein neues Objekt- und Klassenbereich angegeben wird Dies ist umständlich, wenn das gebundene Objekt mehrmals geändert werden muss. Daher stellt PHP7 einen neuen Methodenaufruf bereit, mit dem der Abschluss vorübergehend an ein Objekt gebunden (der Klassenbereich wird auch an das Objekt geändert, zu dem er gehört) (Klasse) und ausgeführt werden kann. Das Beispiel lautet wie folgt:

<?php
class Pandas {
    protected $num = 1;
}
$pandas = new Pandas();
$add = function ($num) {
    $this->num += $num;
    echo $this->num . PHP_EOL;
};
$add->call($pandas, 5);
// 输出 6

Aufrufbar zum Abschluss (PHP7.1)

In PHP7.1 verfügt die Klasse „Closure“ über eine fromCallable-Methode, die den aufrufbaren Typwert in einen Abschluss umwandeln kann. Das Beispiel lautet wie folgt:

<?php
class Foo
{
    protected $num = 1;
    public static function hello(string $bar)
    {
        echo &#39;hello &#39; . $bar;
    }
}
$hello = Closure::fromCallable([&#39;Foo&#39;, &#39;hello&#39;]);
$hello(&#39;world&#39;);

Diese Schreibweise ist ziemlich cool. Schließlich macht der Aufruf über einen Abschluss viel mehr Spaß als der Aufruf mit der Funktion call_user_func ^_^.

0x03 Zusammenfassung

Weitere verwandte Inhalte finden Sie in der Klasse „Closure“ und den anonymen Funktionen. Da die chinesische Version der Klasse „Closure“ im offiziellen PHP-Handbuch nicht aktualisiert wurde, gibt es keinen Inhalt zu den Methoden „call“ und „fromCallable“. . Es wird empfohlen, die englische Version (ㄒoㄒ) zu lesen.

Das obige ist der detaillierte Inhalt vonAnalysieren Sie die Funktionen von PHP-Verschlüssen und Clourse-Klassenmethoden. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.im. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen