The ideal place for storing persistent PHP objects

I’m writing some plugins that do background batch processing, i.e. operations that take longer than 30 seconds. I’m creating objects with the necessary job parameters set like this (this is a hugely simplified example):

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

And in another process:

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

While anywhere else:

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

Now the problem is implementing the Object_Storage. I have figured out the following options for storing objects:

  1. Transients. They apparently won’t do, since they have no guaranteed life-time (with caching, the transients might never be written to the database, I’ve learned).

  2. Existing DB tables. Serialized PHP objects should not be saved to MySQL text fields, since they might contain NULL bytes (( I had a spectacular WSOD failure when serializing an object with a protected property to the usermeta table) :

    Note that this is a binary string which may include null bytes, and
    needs to be stored and handled as such. For example, serialize()
    output should generally be stored in a BLOB field in a database,
    rather than a CHAR or TEXT field. – PHP Manual: serialize()

  3. Creating a custom table with BLOB type fields for serializing any object or alternatively, storing the object data without serializing. Feels like overkill. What are the best practices?

  4. Using the filesystem. Various factors like locking, atomic and non-atomic processes and file permissions complicate this. Specifically, since there will be two processes accessing the object concurrently, there is the problem with race conditions when they need to look at the same object.

  5. Using _SESSION? Probably not good for two concurrent processes.

Any thoughts would be appreciated!

Related posts

2 comments

  1. Long term, you should consider that if you have a process which is going to regularly exceed the max execution time, then running it from inside an HTTP request and polling isn’t a great idea. Consider using the real cron system instead. Command line PHP processes don’t have a max execution time, normally, and can run until completion.

    Short term, if you want to store it safely in a text field, like in a custom post type or meta or something, serialize it, then base64_encode the string. This will solve your problem with the null bytes. Just decode it and unserialize it when you need to retrieve it again.

Comments are closed.