it-swarm.com.de

Der ideale Ort zum Aufbewahren von hartnäckigen PHP Objekte

Ich schreibe einige Plugins für die Hintergrund-Stapelverarbeitung, d. H. Vorgänge, die länger als 30 Sekunden dauern. Ich erstelle Objekte mit den erforderlichen Auftragsparametern wie folgt (dies ist ein enorm vereinfachtes Beispiel):

class MyPlugin_Create_Terms {
    public $job_id;
    public $terms;
    public $taxonomy;
    public $created = 0;
    public function init( $terms, $taxonommy ) {
         $this->job_id = uniqid();
         $this->terms = $terms;
         $this->taxonomy = $taxonomy;
         return $this->job_id;
    }
    public function do_job( $object_storage ) {
         foreach( $this->terms as $term ) {
             wp_insert_term( $term, $this->taxonomy );
             $this->created++;
             $object_storage->save_object( $this->job_id, $this );
         }
    }
}

$create_terms = new MyPlugin_Create_Terms();
$job_id = $create_terms->init( $_POST['user_input_terms'], $_POST['user_input_taxonomy'] );
$object_storage = new MyPlugin_Object_Storage();
$object_storage->save_object( $job_id, $create_terms );

Und in einem anderen Prozess:

$object_storage = new MyPlugin_Object_Storage();
$create_terms = $object_storage->load_object( $job_id );
$create_terms->do_job( $object_storage );

Während anderswo:

$object_storage = new MyPlugin_Object_Storage();
$create_terms = $object_storage->load_object( $job_id );
echo "We have created {$create_terms->created} terms.";

Jetzt implementiert das Problem den Object_Storage. Ich habe die folgenden Optionen zum Speichern von Objekten herausgefunden:

  1. Transienten. Sie werden es anscheinend nicht tun, da sie keine garantierte Lebensdauer haben (beim Caching werden die Transienten möglicherweise nie in die Datenbank geschrieben, wie ich erfahren habe).

  2. Bestehende DB-Tabellen. Serialisierte PHP Objekte sollten nicht in MySQL text Feldern gespeichert werden, da sie NULL Bytes enthalten könnten ((Ich hatte einen spektakulären WSOD-Fehler beim Serialisieren eines Objekts mit einer protected Eigenschaft in der usermeta-Tabelle):

    Beachten Sie, dass dies eine binäre Zeichenfolge ist, die Null-Bytes enthalten kann und als solche gespeichert und behandelt werden muss. Beispielsweise sollte die serialize () - Ausgabe im Allgemeinen in einem BLOB-Feld in einer Datenbank und nicht in einem CHAR- oder TEXT-Feld gespeichert werden. - PHP Manual: serialize ()

  3. Erstellen einer benutzerdefinierten Tabelle mit Feldern vom Typ BLOB zum Serialisieren eines Objekts oder alternativ zum Speichern der Objektdaten ohne Serialisierung. Fühlt sich an wie Overkill. Was sind die Best Practices?

  4. Verwenden des Dateisystems. Verschiedene Faktoren wie Sperren, atomare und nichtatomare Prozesse und Dateiberechtigungen erschweren dies. Da zwei Prozesse gleichzeitig auf das Objekt zugreifen, besteht insbesondere das Problem mit den Race-Bedingungen, wenn dasselbe Objekt betrachtet werden muss.

  5. Verwenden Sie _SESSION? Wahrscheinlich nicht gut für zwei gleichzeitige Prozesse.

Alle mögliche Gedanken würden geschätzt!

4
P_Enrique

Speichern Sie das Objekt vorübergehend in der Datenbank, implementieren Sie jedoch __sleep() UND __wakeup() , um Nebenwirkungen zu vermeiden.

Alternativ können Sie die Schnittstelle Serializable implementieren und die Daten in ihren Methoden vorbereiten. Es ist nicht erforderlich, NULL-Werte zu speichern.

2
fuxia

Langfristig sollten Sie berücksichtigen, dass es keine gute Idee ist, einen Prozess, der regelmäßig die maximale Ausführungszeit überschreitet, aus einer HTTP-Anforderung heraus auszuführen und abzufragen. Verwenden Sie stattdessen das echte Cron-System. Befehlszeile PHP Prozesse haben normalerweise keine maximale Ausführungszeit und können bis zum Abschluss ausgeführt werden.

Kurzfristig, wenn Sie es sicher in einem Textfeld speichern möchten, z. B. in einem benutzerdefinierten Beitragstyp oder Meta oder Ähnlichem, serialisieren Sie es und codieren Sie die Zeichenfolge mit base64_encode. Dies wird Ihr Problem mit den Null-Bytes lösen. Dekodieren Sie es einfach und initialisieren Sie es, wenn Sie es erneut abrufen müssen.

0
Otto