web-dev-qa-db-ja.com

しつこい収納に理想的な場所 PHP オブジェクト

私はバックグラウンドのバッチ処理を行うプラグインを書いています。つまり、30秒以上かかるオペレーションです。必要なジョブパラメータをこのように設定してオブジェクトを作成しています(これは非常に単純化された例です)。

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

そして別のプロセスでは:

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

他のどこかにいる間:

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

今問題はObject_Storageを実装しています。私はオブジェクトを保存するための以下のオプションを考え出しました:

  1. トランジェントそれらは、保証された寿命を持っていないので(キャッシングでは、トランジェントがデータベースに書き込まれることは決してないかもしれない、と私は学びました)、それらはどうしてもしないでしょう。

  2. 既存のDBテーブルシリアル化されたPHPオブジェクトは、textバイトを含む可能性があるため、MySQLのNULLフィールドに保存しないでください(protectedプロパティを持つオブジェクトをusermetaテーブルにシリアル化するとき、壮大なWSODエラーが発生しました)。

    これは、nullバイトを含む可能性があるバイナリ文字列であり、そのように格納して処理する必要があることに注意してください。たとえば、serialize()の出力は通常、CHARまたはTEXTフィールドではなく、データベースのBLOBフィールドに格納する必要があります。 - PHP Manual:serialize()

  3. 任意のオブジェクトをシリアル化するため、またはシリアル化せずにオブジェクトデータを格納するためのBLOB型フィールドを持つカスタムテーブルを作成します。やり過ぎのように感じます。ベストプラクティスは何ですか?

  4. ファイルシステムを使うロック、アトミックおよび非アトミックプロセス、ファイルのアクセス権などのさまざまな要素がこれを複雑にします。具体的には、オブジェクトに同時にアクセスする2つのプロセスがあるので、それらが同じオブジェクトを見る必要があるときに競合状態に問題があります。

  5. _SESSIONを使用しますか?おそらく2つの同時プロセスには向いていません。

どんな考えでもありがたいです!

4
P_Enrique

オブジェクトを一時的にデータベースに格納しますが、副作用を避けるために __sleep()__wakeup() を実装します。

あるいは、 Serializableインターフェース を実装し、そのメソッドでデータを準備します。 NULL値を格納する必要はありません。

2
fuxia

長期的には、あなたが定期的に最大実行時間を超えようとしているプロセスがあるならば、HTTPリクエストとポーリングの内側からそれを実行することは素晴らしい考えではないということを考慮すべきです。代わりに本物のcronシステムを使用することを検討してください。コマンドラインPHPプロセスは、通常、最大実行時間がなく、完了するまで実行できます。

短期間で、カスタム投稿タイプやメタなどのテキストフィールドに安全に格納する場合は、シリアル化してから、文字列をbase64_encodeにします。これはあなたの問題をnullバイトで解決するでしょう。それをデコードして、もう一度取得する必要があるときにシリアル化を解除するだけです。

0
Otto