Aktueller Standort: Startseite> Neueste Artikel> Wie vermeiden Sie die Falle der unendlichen Rekursion bei der Verwendung von PHP -Serialisierungsfunktion?

Wie vermeiden Sie die Falle der unendlichen Rekursion bei der Verwendung von PHP -Serialisierungsfunktion?

gitbox 2025-05-19

In der PHP -Programmierung wird die Serialisierungsfunktion verwendet, um Objekte oder Arrays in Zeichenfolgen umzuwandeln, sodass sie gespeichert oder übertragen werden können. Wenn wir jedoch Objekte serialisieren, wenn es Attribute in dem Objekt gibt, die sich auf andere Objekte beziehen und es eine gegenseitige Referenzbeziehung zwischen diesen Objekten gibt (z. B. A bezieht sich auf B, und B bezieht sich auf a), kann dies eine unendliche Rekursion verursachen, was wiederum einen Stapelüberlauf verursacht und schließlich zu einem Skriptabsturz führt.

In diesem Artikel wird untersucht, wie die Falle der unendlichen Rekursion bei der Verwendung von PHP -Serialisierungsfunktion vermieden wird.

1. Grundnutzung von Serialisierungsfunktionen

Die Serialisierungsfunktion in PHP wandelt PHP -Werte in ein Format um, das gespeichert oder übertragen werden kann. Normalerweise zur anhaltenden Speicherung von Objekten oder Arrays verwendet. Zum Beispiel:

 <?php
$array = array("name" => "GitBox", "url" => "https://gitbox.net");
$serialized = serialize($array);
echo $serialized;
?>

2. Die Erzeugung der unendlichen Rekursion

Die Falle der unendlichen Rekursion tritt normalerweise auf, wenn zwischen Objekten eine kreisförmige Referenz vorliegt. Zum Beispiel:

 <?php
class Node {
    public $name;
    public $child;
    
    public function __construct($name) {
        $this->name = $name;
    }
    
    public function setChild($child) {
        $this->child = $child;
    }
}

$node1 = new Node("Node 1");
$node2 = new Node("Node 2");
$node1->setChild($node2);
$node2->setChild($node1);

$serialized = serialize($node1); // Dies führt zu einer unendlichen Rekursion
?>

Im obigen Code beziehen sich $ node1 und $ node2 aufeinander. Wenn Serialize ($ node1) aufgerufen wird, startet PHP das serialisierende Objekt $ node1 , das die untergeordnete Eigenschaft von Node1 serialisieren wird, und die untergeordnete Eigenschaft zeigt auf $ node2 . Dann wird PHP $ node2 weiter serialisieren und dann zu serialisieren $ node1 , was zu einer unendlichen Rekursion führt, was zu einem Speicherüberlauf führt.

3.. Wie kann man unendlich rekursion vermeiden

Um nicht in die Falle der unendlichen Rekursion bei der Verwendung von Serialisierung zu fallen, können wir die folgenden Methoden annehmen:

3.1 Mit __sleep -Magic -Methode

PHP liefert eine magische Methode , mit der wir angeben können, welche Eigenschaften serialisiert werden sollten. Wenn ein Objektattribut eine Rekursion verursacht, verwenden Sie die __Sleep -Methode, um diese Attribute herauszufiltern.

 <?php
class Node {
    public $name;
    public $child;
    
    public function __construct($name) {
        $this->name = $name;
    }

    public function setChild($child) {
        $this->child = $child;
    }

    public function __sleep() {
        return ['name']; // Nur Serialisierung $name Eigentum,Vermeiden Sie kreisförmige Referenzen
    }
}

$node1 = new Node("Node 1");
$node2 = new Node("Node 2");
$node1->setChild($node2);
$node2->setChild($node1);

$serialized = serialize($node1); // Hier passiert keine Rekursion
echo $serialized;
?>

Durch die Rückgabe einer Liste von Attributen in __Sleep können wir steuern, welche Attribute serialisiert werden, wodurch eine Rekursion vermieden wird.

3.2 Verwenden Sie SplpObjectStorage , um Objekte zu speichern

SprobjectStorage ist eine Klasse, die speziell zum Speichern von Objekten verwendet wird, wodurch bei der Speicherung von doppelten Objekten rekursionsprobleme vermieden werden können. Wir können es verwenden, um Rekursionsprobleme zu vermeiden.

 <?php
class Node {
    public $name;
    public $child;
    
    public function __construct($name) {
        $this->name = $name;
    }

    public function setChild($child) {
        $this->child = $child;
    }
}

$node1 = new Node("Node 1");
$node2 = new Node("Node 2");
$node1->setChild($node2);
$node2->setChild($node1);

$storage = new SplObjectStorage();
$storage->attach($node1);
$storage->attach($node2);

$serialized = serialize($storage); // Hier passiert keine Rekursion
echo $serialized;
?>

SprobjectStorage verfolgt intern die Verweise auf Objekte, sodass wir die durch kreisförmige Referenzen verursachte unendliche Rekursion vermeiden können.

3.3 benutzerdefinierte __wakeup Magic -Methode

In einigen Fällen möchten wir beim Wiederherstellen des serialisierten Objekts einige zusätzliche Überprüfungen durchführen. PHP liefert die __Wakeup Magic -Methode, mit der wir einige Operationen bei der Deserialisierung von Objekten ausführen können.

 <?php
class Node {
    public $name;
    public $child;
    
    public function __construct($name) {
        $this->name = $name;
    }

    public function setChild($child) {
        $this->child = $child;
    }

    public function __wakeup() {
        if ($this->child === $this) {
            $this->child = null; // Verhindern Sie zirkuläre Referenzen während der Deserialisierung
        }
    }
}

$node1 = new Node("Node 1");
$node2 = new Node("Node 2");
$node1->setChild($node2);
$node2->setChild($node1);

$serialized = serialize($node1); 
echo $serialized;

$unserialized = unserialize($serialized); // Die kreisförmige Referenz wird hier automatisch gelöscht
?>

Bei der __Wakeup -Methode erkennen und löschen wir die Loop -Referenz, um bei der Deserialisierung erneut eine Rekursion zu vermeiden.


Durch diese Methoden können wir die unendlichen Rekursionsprobleme, die durch PHP -Serialisierung verursacht werden können, effektiv vermeiden, um sicherzustellen, dass das Programm bei der Verarbeitung von Objekten aufgrund kreisförmiger Referenzen nicht abstürzt. Ich hoffe, dieser Artikel hilft Ihnen, besser zu verstehen, wie Sie rekursive Fallen vermeiden können, wenn Sie Serialisierungsfunktionen in PHP verwenden. Wenn Sie Fragen haben, besprechen Sie bitte weiter!