TiMESPLiNTER TiMESPLiNTER - 1 month ago 7
PHP Question

Check if an object has changed

Is there a more native way (e.x. a built-in function) with less userland code to check if an objects property values have changed instead of using one of those methods:

The serialize approach

$obj = new stdClass(); // May be an instance of any class

echo $hashOld = md5(serialize($obj)) . PHP_EOL;

$obj->change = true;

echo $hashNew = md5(serialize($obj)) . PHP_EOL;

echo 'Changed: '; var_dump($hashOld !== $hashNew);


Which results in:

f7827bf44040a444ac855cd67adfb502 (initial)
506d1a0d96af3b9920a31ecfaca7fd26 (changed)
Changed: bool(true)


The shadow copy approach

$obj = new stdClass();
$shadowObj = clone $obj;

$obj->change = true;

var_dump($shadowObj != $obj);


Which results in:

bool(true);


Both approaches work. But both have disadvantages compared to a non userland implementation. The first one needs CPU for serialization and hashing and the second one needs memory for storing clones. And some classes may not be cloned.

Doesn't PHP track changes at object properties? And does PHP not expose a method to make use of it?

Answer

What you are trying to do?

You are trying to compare object with itself, after some chain of "unknown" operations to check if the object has changed. If this is true, there are some logical points to observe. At first, if you want to compare object with itself, you've got only two options:

  1. Remember the whole object state (for example hash, or just copy whole object)
  2. Track changes over time

There is no other logical approach. Comparing memory allocations, real objects, copying objects, comparing hashes, is all in point one. Tracking changes, saving changes inside object, remembering meantime operations, inside point 2.

So in my opinion this question is sort of backing up data questions. In that case there are many, many solutions but none of them are hardcoded inside php as far as I'm concerned. Why?


The answer is simple. PHP guys have got the same problems you've got :). Because if this would be hardocded inside php, then php should run / use one of those mechanisms (1) or (2).

In that case every object that you create, and every operation you made should be written somewhere to remember every state / object / something and use them for comparison in the future.

While you need this solution, almost ~100% of websites don't. So hardcoding this inside php would made ~100% of websites work slower and your work faster ;).


PHP hypothetical solution?

The only solution (maybe built in php in the future) I can think of is making some kind of php config flag: track objects, and only if this flag is true, then run all the php mechanisms of tracking objects states. But this also mean a huge performance gap. As all the ifs (if tracking, if tracking, if tracking) are also procesor and memory time consuming.

There is also a problem, what to compare? You need to compare object with same object, but... Few minutes ago? Few operations ago? No... You must point exactly one place in code, and then point second place in code and compare object in those two places. So hypothetical auto tracking is... Kind of powerless, as there is no "key" in the object state ofer time array. I mean, even if you got magic_object_comparer function, what it should look like?

<?php

    function magic_object_comparer() {} // Arguments??
    function magic_object_comparer($object_before, $object_after) {} // you must save object_before somewhere...??
    function magic_object_comparer($object, $miliseconds) {} // How many miliseconds?
    function magic_object_comparer($object, $operations) {} // How many operations? Which operations?


    magic_comparer_start($object);
    // ... Few operations...
    $boolean = magic_comparer_compare_from start($object);
    // Same as own implementation...
?>

Sadly, you are left with own implementation...

After all, I would propose to implement some kind of own mechanism for that, and remember to use it only there, where you need it. As this mechanism will for sure be time and memory consuming. So think carefully:

  1. Which objects you want to compare. Why?
  2. When you want to compare them?
  3. Does all changes need to be compared?
  4. What is the easiest way of saving those states changes?

And after all of that, try to implement it. I see that you've got a huge php knowledge, so I'm pretty sure that you will figure out something. There are also many comments, and possible ideas in this question and discussion.


But after all maybe I explained a little why, there is no build in solution, and why there should not be one in the future... :).


UPDATE

Take a look here: http://www.fluffycat.com/PHP-Design-Patterns/. This is a great resource about php patterns. You should take a look at adapter, decorator and observer patterns, for possible elegant object oriented solutions.