web-dev-qa-db-fra.com

L'endroit idéal pour stocker persistant PHP objets

J'écris des plugins qui effectuent un traitement par lots en arrière-plan, c'est-à-dire des opérations qui durent plus de 30 secondes. Je crée des objets avec les paramètres de travail nécessaires définis comme ceci (voici un exemple extrêmement simplifié):

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 );

Et dans un autre processus:

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

Partout ailleurs:

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

Maintenant le problème implémente le Object_Storage. J'ai compris les options suivantes pour stocker des objets:

  1. Transitoires. Ils ne le feront apparemment pas, car ils n'ont aucune durée de vie garantie (avec la mise en cache, les transitoires pourraient ne jamais être écrits dans la base de données, j'ai appris).

  2. Tables de base de données existantes. Les objets PHP sérialisés ne doivent pas être enregistrés dans les champs text de MySQL, car ils peuvent contenir des octets NULL ((j'ai eu un échec WSOD spectaculaire lors de la sérialisation d'un objet avec une propriété protected dans la table usermeta):

    Notez qu'il s'agit d'une chaîne binaire pouvant inclure des octets nuls. Elle doit être stockée et traitée comme telle. Par exemple, la sortie serialize () doit généralement être stockée dans un champ BLOB d'une base de données, plutôt que dans un champ CHAR ou TEXT. - PHP Manuel: serialize ()

  3. Création d'une table personnalisée avec des champs de type BLOB pour sérialiser un objet ou pour stocker les données d'objet sans sérialisation. Je me sens exagéré. Quelles sont les meilleures pratiques?

  4. Utiliser le système de fichiers. Divers facteurs tels que le verrouillage, les processus atomiques et non atomiques et les autorisations de fichiers compliquent cette situation. Plus précisément, étant donné que deux processus accéderont à l'objet simultanément, le problème des conditions de concurrence se pose lorsqu'ils doivent examiner le même objet.

  5. Utiliser _SESSION? Probablement pas bon pour deux processus simultanés.

Toute réflexion sera apprécié!

4
P_Enrique

Stockez l'objet temporairement dans la base de données, mais implémentez __sleep() ET __wakeup() pour éviter les effets secondaires.

Sinon, implémentez l'interface Serializable et préparez les données dans ses méthodes. Il n'est pas nécessaire de stocker des valeurs NULL.

2
fuxia

À long terme, vous devriez considérer que si vous avez un processus qui dépasse régulièrement le temps d'exécution maximal, il ne peut être utile de l'exécuter à partir d'une requête HTTP. Pensez plutôt à utiliser le vrai système cron. Les processus en ligne de commande PHP n'ont pas de temps d'exécution maximal, normalement, et peuvent s'exécuter jusqu'à la fin.

À court terme, si vous souhaitez le stocker en toute sécurité dans un champ de texte, comme dans un type de message personnalisé, une méta ou quelque chose de ce genre, sérialisez-le, puis base64_encode la chaîne. Cela résoudra votre problème avec les octets nuls. Il suffit de le décoder et de le désérialiser lorsque vous devez le récupérer à nouveau.

0
Otto