2012-03-26 12 views
7

Angenommen, ich habe ein Objekt - in diesem Fall ein Benutzerobjekt -, und ich möchte Änderungen mit einer separaten Klasse verfolgen können. Das Benutzerobjekt sollte sein Verhalten in keiner Weise ändern müssen, damit dies geschieht.Was ist der schnellste Weg, um zwei Objekte in PHP zu vergleichen?

Daher erstellt meine separate Klasse eine "saubere" Kopie davon, speichert sie irgendwo lokal und kann später das Benutzerobjekt mit der ursprünglichen Version vergleichen, um zu sehen, ob sich etwas während seiner Lebensdauer geändert hat.

Gibt es eine Funktion, ein Muster oder irgendetwas, das die beiden Versionen des Benutzerobjekts schnell vergleichen kann?

Option 1 Vielleicht könnte ich jede Version serialisieren und direkt vergleichen oder Hash-und vergleichen?

Option 2 Vielleicht schaffe ich sollte einfach ein Reflection, durch jede der Eigenschaften der Klasse laufen und sehen, ob die beiden Versionen die gleichen Eigenschaftswerte haben?

Option 3 Vielleicht ist es eine einfache native Funktion wie objects_are_equal($object1,$object2);?

Was ist der schnellste Weg, dies zu tun?

+0

Nun, ich weiß, ich könnte beide Objekte serialisieren, und Hashes oder etwas vergleichen .... es ist nicht, ob ich kann, es geht eher darum, wie mache ich es schnell? Ich werde die Frage adjustieren, um diesen Geist zu reflektieren ... – johnnietheblack

Antwort

9

Die einzige Möglichkeit, auf alle (öffentlichen, geschützten und privaten) Eigenschaften eines Objekts zuzugreifen, ohne es zu ändern, ist reflection. Sie könnten, wenn Sie möchten, das Objekt vor der Änderung clone vergleichen und dann mit den Reflexionsfunktionen vergleichen, um die verschiedenen Eigenschaften eines der beiden Objekte zu durchlaufen und Werte zu vergleichen. Das würde Ihnen effektiv sagen, welche Eigenschaften sich geändert haben.

Wenn Sie nur sehen möchten, ob sich die Objekte geändert haben, können Sie die Operatoren == oder === verwenden. Werfen Sie einen Blick auf den Abschnitt comparing objects der PHP-Dokumentation.

Das heißt, wäre es nicht einfacher zu verfolgen, was Sie geändert haben, wenn Sie sie ändern?

+0

Danke für die Antwort :) Ich könnte, aber ich recherchiere Doctrine2, und es scheint, als ob sie eine riesige Grafik von Objekten erstellen, und beim Aufruf von flush(), Sie prüfen, was sich geändert hat, und aktualisieren alles auf einen Schlag ... was ich versuche herauszufinden. – johnnietheblack

+0

@johnnietheblack - Sie könnten Doctrine-Ereignisse verwenden, aber dazu müssten Ihre Objekte leicht geändert werden. Wenn Sie sich für Doctrine-Ereignisse interessieren, werfen Sie einen Blick auf http://stackoverflow.com/questions/2059399/doctrine-listener-run-action-only-if-a-field-haschanged. Es ist für Documen 1.2, aber das Prinzip ist das gleiche in der neueren Version. –

+0

Nochmals vielen Dank - Ich möchte die Benutzerklasse in keiner Weise anpassen müssen, damit ich den "Listener" entfernen konnte und der Benutzer den Unterschied nicht kennen würde. Außerdem würde ich gerne lernen, wie man dies ohne Doctrine tut ... teilweise zum Spaß, und teilweise, wenn ich jemals wissen muss, wie es sonst gemacht wird – johnnietheblack

2

Es gibt eine ganze Seite auf php.net ist nur mit dem Vergleich Objekten zu tun:

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

auch gut zu lesen:

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

Ich würde sagen, Sie die verwenden sollten " clone "-Methode beim Kopieren deines Objektes und vergleiche später wie im php.net-Artikel beschrieben.

Auch ein schneller Weg wäre, eine statische Methode in der Klasse zu deklarieren, die nur die relevanten "Eigenschaften" vergleicht, wie sagen wir "Benutzername", "Passwort", "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

Danke für die Artikel .... ich werde jetzt checkem – johnnietheblack

+0

Das Update ist sehr gut, wie ich in der Frage gesagt habe ... Ich möchte, dass der Benutzer nichts ändern muss, um diesen Vergleich zu machen Möglich ... – johnnietheblack

+0

das ist ein Grund, warum statische Methoden existieren, um zwischen Objekten der gleichen Klasse zu interagieren :) Mit dieser Methode können Sie auch schnell bestimmen, welche "Eigenschaft" sich geändert hat, indem Sie einfach eine Assoziation zurückgeben. Array wie $ result ["Benutzername" => "gleich", "Passwort" => "gleich", "Cookie" => "anders"] –

1

Hier ist ein Stück Code, das private Eigenschaften unterstützt:

$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 { 
     // ... 
    } 
} 


Beachten Sie, dass, wenn $object_1 hat Eigenschaften, die $object_2 nicht, die oben Codefehler erzeugen haben, wenn zugreifen möchten Sie.

Für einen solchen Fall müssten Sie zuerst $reflection_1->getProperties() mit $reflection_2->getProperties() schneiden.

Verwandte Themen