5

これは SO に関する私の最初の質問ですが、かなり検索しました。すでに触れていたらすみません。

質問/問題は、PHP の serialize() 機能に関係しています。オブジェクトをデータベースに格納するためにシリアル化を使用しています。例えば:

class Something {
  public $text = "Hello World";
}

class First {

  var $MySomething;

  public function __construct() {
    $this->MySomething = new Something();
  }
}

$first_obj = new First();
$string_to_store = serialize($first_obj);

echo $string_to_store

//  Result:  O:5:"First":1:{s:11:"MySomething";O:9:"Something":1:{s:4:"text";s:11:"Hello World";}}

さて、プロジェクト生活の後半で、私は自分のクラスを変更したいと思います。まず、何かのオブジェクトにも対応する新しいプロパティ $SomethingElse を持ちます。

問題は、古い/既存のオブジェクトの場合、First クラスの新しいバージョンにシリアル化を解除するときに、新しいプロパティ (SomethingElse) を初期化する唯一の方法は、__wakeup() メソッドでそれを探すことです。その場合、そこに新しいプロパティを文書化する必要があります。これは正しいです?プロパティはコンストラクタのように扱われ、初期値が設定されている必要があります (最終的にコードが複製されます)。

変数を宣言するときに変数を初期化すると、たとえば、Something クラスを次のように変更すると、シリアル化解除によって取得されることがわかりました。

class Something {
  public $text = "Hello World";
  public $new_text = "I would be in the unserialized old version.";
}

...

$obj = unserialize('O:5:"First":1:{s:11:"MySomething";O:9:"Something":1:{s:4:"text";s:11:"Hello World";}}');

print_r($obj);

//  Result:  First Object ( [MySomething] => Something Object ( [text] => Hello World [new_text] => I would be in the unserialized old version. ) ) 

ただし、新しいプロパティを宣言するときにオブジェクトに初期化することはできません。これは、コンストラクター (および __wakeup()?) で行う必要があります。

これを十分に説明したことを願っています。このあたりに欠けているプログラミング パターンがあるかどうか、または __wakeup() で初期化コードを複製する (または init メソッドを参照する) ことが一般的かどうか、または単に古いオブジェクトを新しいバージョンに移行する準備が必要かどうかを知りたい経由。移行スクリプト。

ありがとう。


更新: これまでのコメンターの発言を考えて、init() メソッドを使用して更新された First クラスを投稿すると思いました。

class Something {
  public $text = "Hello World2";
  public $new_text = "I would be in the unserialized old version.2";
}

class First {

  var $MySomething;
  var $SomethingElse;

  public function __construct() {
    $this->init();
  }

  public function __wakeup() {
    $this->init();
  }
  private function init() {
    if (!isset($this->MySomething)) {
      $this->MySomething = new Something();
    }
    if (!isset($this->SomethingElse)) {
      $this->SomethingElse = new Something();
    }
  }
}

$new_obj = unserialize('O:5:"First":1:{s:11:"MySomething";O:9:"Something":1:{s:4:"text";s:11:"Hello World";}}');

print_r($new_obj);

//  Result:  First Object ( [MySomething] => Something Object ( [text] => Hello World [new_text] => I would be in the unserialized old version.2 ) [SomethingElse] => Something Object ( [text] => Hello World2 [new_text] => I would be in the unserialized old version.2 ) ) 

それは私にとって実行可能なパターンのように思えるので、本当にわかりません。クラスが新しいプロパティを取得すると、最初の復元時にデフォルト値が取得されます。

4

2 に答える 2

2

良い質問!一概には答えられません。そして、それは単に serialize(). に関連しているのではありません。SQL データベースがあり、コードが変更された場合、古いデータでも機能しません。これは、データ(ベース)を使用したバージョン管理の一般的な問題です。

古いソフトウェア バージョンのデータを新しいバージョンに統合する場合、ほとんどの場合、古いデータを新しい形式に変換する必要があるという問題が発生します。それは設定ファイルなどにも当てはまります...

このような場合、古いデータを新しい形式に変換するスクリプトを作成するのが一般的です。私は、サーバー製品の PHP 'ファームウェア' のアップグレード パッケージを作成するときに、仕事でこれを数年間行ってきました。:) Linux ディストリビューションのほとんどのパッケージ マネージャーも同様です。

: アップグレード間のデータ損失に対して安全な場合は、開発中に注意を払い、データの「アップグレード可能性」を念頭に置く必要があります。


更新: シリアル化されたデータは、データの更新プロセスをさらに悪化させる可能性があると思います。クラスをシリアライズして名前を変更するとどうなりますか? データの取得が困難になります。これは考えたこともなかったのですが、バージョンアップの際に問題になりそうです。

于 2013-02-27T01:26:29.380 に答える
0

前回、プロパティを変更するクラスを作成したとき、すべてのデータを $classVar という連想配列に格納しました。これを行うと、追加するすべての変数は、追加する変数の数に関係なく、1 つの単純なシリアル化呼び出しで追跡されます。

使用に関しては、変数が初期化されているかどうかを確認し、そうでない場合はデフォルトを設定します。classversion 変数をシリアル化して、使用されなくなった変数や変換が必要な変数などのより複雑なケースを処理することもできます

于 2013-02-27T01:20:07.670 に答える