2012-03-26 19 views
7

Diciamo che ho un oggetto - un oggetto Utente in questo caso - e mi piacerebbe essere in grado di tenere traccia delle modifiche con una classe separata. L'oggetto Utente non dovrebbe modificare il suo comportamento in alcun modo perché ciò avvenga.Qual è il modo più veloce per confrontare due oggetti in PHP?

Pertanto, la mia classe separata crea una copia "pulita" di esso, la memorizza da qualche parte a livello locale, e successivamente può confrontare l'oggetto Utente con la versione originale per vedere se qualcosa è cambiato durante la sua durata.

Esiste una funzione, un modello o qualcosa che possa confrontare rapidamente le due versioni dell'oggetto Utente?

Opzione 1 forse potrei serializzare ogni versione, e direttamente confrontare, o hash e confrontare?

Opzione 2 Forse dovrei semplicemente creare un ReflectionClass, gestito attraverso ciascuno dei proprietà della classe e vedere se le due versioni hanno gli stessi valori delle proprietà?

Opzione 3 Forse c'è una semplice funzione nativa come objects_are_equal($object1,$object2);?

Qual è il modo più veloce per farlo?

+0

Beh, so che potrei serializzare entrambi gli oggetti e confrontare gli hash o qualcosa del genere ... non è se POSSO, è più su come lo faccio rapidamente? Aggiungerò la domanda per riflettere quello spirito ... – johnnietheblack

risposta

9

L'unico modo per accedere a tutte le proprietà (pubbliche, protette e private) di un oggetto senza modificarlo è tramite reflection. È possibile, se lo si desidera, clone l'oggetto prima di essere modificato e quindi confrontarli utilizzando le funzioni di riflessione per scorrere tra le diverse proprietà di uno dei due oggetti e confrontare i valori. Questo ti direbbe effettivamente quali proprietà sono cambiate.

Se tutto quello che interessa è vedere se gli oggetti sono stati modificati o meno, è possibile utilizzare gli operatori == o ===. Dai un'occhiata alla sezione comparing objects della documentazione di PHP.

Detto questo, non sarebbe più semplice tenere traccia di ciò che hai cambiato mentre li hai modificati?

+0

Grazie per la risposta :) Potrei, ma sto facendo ricerche su Doctrine2, e sembra come se creassero un gigantesco grafico di oggetti, e dopo aver chiamato flush(), controllano per vedere cosa è cambiato e aggiornano tutto in un colpo solo ... che è quello che sto cercando di capire. – johnnietheblack

+0

@johnnietheblack - È possibile utilizzare gli eventi Doctrine, ma ciò richiederebbe che gli oggetti vengano leggermente modificati. Se sei interessato agli eventi di Doctrine, dai un'occhiata a http://stackoverflow.com/questions/2059399/doctrine-listener-run-action-only-if-a-field-has-changed. È per Doctrine 1.2 ma il principio è lo stesso nella versione più recente. –

+0

Grazie ancora - Mi piacerebbe non dover aggiustare la classe User in alcun modo, in modo da poter rimuovere il "listener" e l'utente non conoscerebbe la differenza. Inoltre, mi piacerebbe imparare come fare questo senza la Dottrina ... in parte per divertimento, e in parte se ho sempre bisogno di sapere come è fatto altrimenti – johnnietheblack

2

C'è un intero sito su php.net solo che fare con oggetti a confronto:

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

anche una buona lettura:

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

direi si dovrebbe usare il " clone "quando copi il tuo oggetto e poi confrontalo come detto nell'articolo di php.net.

Anche un modo veloce sarebbe dichiarando un metodo statico nella classe che confronta solo le "proprietà" rilevanti come diciamo "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

Grazie per gli articoli .... Verificherò ora – johnnietheblack

+0

L'aggiornamento è molto buono, come ho detto nella domanda ... Mi piacerebbe che l'utente non debba modificare NULLA per fare questo confronto possibile ... – johnnietheblack

+0

questo è un motivo per cui esistono metodi statici, per interagire tra oggetti della stessa classe :) con questo metodo è anche possibile determinare velocemente quale "proprietà" è stata modificata semplicemente restituendo un socio. array come $ result ["username" => "same", "password" => "same", "cookie" => "different"] –

1

Ecco un pezzo di codice che supporta le proprietà private:

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


Nota che se $object_1 ha proprietà che $object_2 non ha, il codice di cui sopra produrrà gli errori quando si cerca di accedere loro.

Per questo caso, è necessario prima intersecare $reflection_1->getProperties() con $reflection_2->getProperties().

Problemi correlati