2012-03-26 18 views
7

私はオブジェクト(この場合Userオブジェクト)を持っていて、別のクラスで変更を追跡できるようにしたいとします。このためには、Userオブジェクトの動作を変更する必要はありません。PHPで2つのオブジェクトを比較する最も速い方法は何ですか?

したがって、私の別のクラスは、その「クリーン」なコピーを作成し、それをローカルのどこかに格納し、その後、元のバージョンと比較して、その寿命の間に何かが変更されたかどうかを調べることができます。

Userオブジェクトの2つのバージョンをすばやく比較できる関数、パターンなどがありますか?

オプション1 多分、私は各バージョンをシリアル化し、直接比較するか、ハッシュして比較することができますか?

オプション2 たぶん私は単に、ReflectionClassを作成するクラスのプロパティのそれぞれを介して実行し、2つのバージョンが同じプロパティ値を持っているかどうかを確認する必要がありますか?

オプション3 おそらくobjects_are_equal($object1,$object2);のような単純なネイティブ関数がありますか?

これを行う最も簡単な方法は何ですか?

+0

まあ、私は両方のオブジェクトをシリアル化し、ハッシュなどを比較することができることは知っています....それは私ができるかどうかではありません。私はその精神を反映するために質問をアシストするでしょう... – johnnietheblack

答えて

9

オブジェクトのすべての(公開、保護、およびプライベート)プロパティに変更を加えずにアクセスする唯一の方法は、reflectionです。もし望むなら、オブジェクトを変更する前にcloneオブジェクトを編集し、2つのオブジェクトの1つの異なるプロパティをループして値を比較するためにリフレクション関数を使用してオブジェクトを比較することができます。それは効果的にどのプロパティが変更されたかを伝えます。

オブジェクトが変更されているかどうかは、==または===演算子を使用して確認できます。 PHPのドキュメントのcomparing objectsのセクションを見てください。

あなたが変更したものを変更したことを把握するのは簡単ではないでしょうか?

+0

答えをありがとう:)私はできますが、私はDoctrine2を研究しています、そして、彼らはオブジェクトの巨大なグラフを作成し、flush()彼らは何が変わったのかを確認し、一気にすべてを更新します。これは私が把握しようとしているものです。 – johnnietheblack

+0

@ johnnietheblack - あなたはDoctrineイベントを使うことができますが、それはあなたのオブジェクトを少し修正する必要があります。 Doctrineイベントに興味がある場合は、http://stackoverflow.com/questions/2059399/doctrine-listener-run-action-only-if-a-field-has-changedをご覧ください。それはDoctrine 1.2のためですが、原則は新しいバージョンでも同じです。 –

+0

もう一度ありがとう - 私は "リスナー"を削除することができ、ユーザーが違いを知らないように、何らかの方法でUserクラスを調整する必要はありませんしたいと思います。また、私はdoctrineを使ってこれを行う方法を学びたいと思っています...一部は楽しく、一部はそれが他の方法でどうなっているかを知る必要がある場合は部分的に – johnnietheblack

2

サイト全体だけで比較するオブジェクトを扱うphp.netにあります:

http://php.net/manual/en/language.oop5.object-comparison.php

も良い読み取り:

http://www.tuxradar.com/practicalphp/6/12/0

は、私はあなたが使うべきだと思います」クローン "メソッドを使用してオブジェクトをコピーし、後でphp.netの記事で述べたように比較します。

また、「username」、「password」、「cookie」などのような関連する「プロパティ」を比較するクラスで静的メソッドを宣言するのが速い方法です。ここで

class User 
    { 

    public $username; 
    public $password; 
    public $cookie; 

    # other code 

    public static function compare(&$obj1, &$obj2) 
    { 
    if ($obj1->username != $obj2->username) 
     return 0 
    if ($obj1->password != $obj2->password) 
     return 0 
    if ($obj1->cookie != $obj2->cookie) 
     return 0 
    return 1 
    } 


    };  
+0

記事をありがとう....私は今すぐチェックアウトします – johnnietheblack

+0

私は質問で言ったように、更新は非常に良いです...私はこの比較を行うために何も変更する必要はありません可能... – johnnietheblack

+0

静的メソッドが存在する理由は、同じクラスのオブジェクト間でやりとりする:)このメソッドを使用すると、単純にassocを返すことでどの "プロパティ"が変更されたかを判断することもできます。 $ result ["username" => "same"、 "password" => "same"、 "cookie" => "different"]のような配列 –

1

は、プライベートプロパティをサポートしているコードの一部です:$object_1$object_2が持っていない性質を持っている場合は、アクセスしようとすると、上記のコードはエラーを生成することを

$reflection_1 = new \ReflectionClass($object_1); 
$reflection_2 = new \ReflectionClass($object_2); 

$props_1 = $reflection_1->getProperties(); 

foreach ($props_1 as $prop_1) { 

    $prop_1->setAccessible(true); 
    $value_1 = $prop_1->getValue($object_1); 

    $prop_2 = $reflection_2->getProperty($prop_1->getName()); 

    $prop_2->setAccessible(true); 
    $value_2 = $prop_2->getValue($object_2); 

    if ($value_1 === $value_2) { 
     // ... 
    } else { 
     // ... 
    } 
} 


は注意それら。

このような場合、最初に$reflection_1->getProperties()$reflection_2->getProperties()と交差する必要があります。

関連する問題