10

I use a data class to feed templates my data, I want to calculate a unique id from the data in the data class so I can check if the template with that data is already in cache and then serve that version.

so a function to get an unique id from an array of a class would help me out.

something like this works but is rather costly md5(serialize($classdata))

I'm hoping there is some function to get the unique id without serializing all data, or at least not to have to in php.

edit:
I celebrated too soon, the unique id is only the same in the current instance a restart of the same script makes another id, which then of course is not in cache.

testscript used:

<?php
class foo {}
$f = new foo;
print spl_object_hash($f);

I'll explain in some more depth

class template_data implements IteratorAggregate, ArrayAccess, Countable {
    
    private $_data;
    
    //some methods for the overloaded classes
    //
    
    //the getId function
    public function getId() {
        return hash('md5',serialize($this->_data));
    }
    
}

$t = new template('file');
$d = new template_data('some data');
$t->addData($d);
$t->display();

Now if the data given to the template engine is in cache it uses that version preventing to having to re-parse the template for the dataset.

This is a simplistic view of the template_data, it is actually lazy loading and uses memcached dataid's so the data isn't actually fetched till it is used in the template.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Paul Scheltema
  • 1,993
  • 15
  • 25

3 Answers3

5

You could try spl_object_hash()

From the docs

This function returns a unique identifier for the object. This id can be used as a hash key for storing objects or for identifying an object.

Jake N
  • 10,535
  • 11
  • 66
  • 112
  • ok so after some testing the object hash is different every instance of php, so if i reload the page a few times i get a new unique hash every time, i need the hashes to remain the same across multiple php instances/page refreshes – Paul Scheltema Jan 19 '11 at 15:07
  • 1
    `spl_object_hash()` will generate a unique hash for the object compared to other objects in *current memory*, not across the board. And even then, [`when an object is destroyed, its hash may be reused for other objects`](http://php.net/manual/en/function.spl-object-hash.php) – Boaz Feb 21 '13 at 12:11
2

PHP does not create unique IDs that persist between executions for objects, this means that you are going about producing the desired behavior correctly. So while there is no good answer for the asked question I can give some suggestions to reduce the cost of producing your IDs.

First you can use json_encode rather than serialize. Second, you can store the value, so that multiple calls to the function will not re-serialize the data every time.

The json_encode function is not only faster than serialize, but it also produces a shorter string as output.

http://cw-internetdienste.de/2015/05/04/serialize-vs-json_encode/

class template_data implements IteratorAggregate, ArrayAccess, Countable {

    private $_data;
    private $_id;

    //
    //some methods for the overloaded classes
    //

    //the getId function
    public function getId() {
        if(empty($this->_id))
            $this->_id = hash('md5',json_encode($this->_data));

        return $this->_id;
    }
}

Lastly; the best solution will probably be to cache the output of the template using the route, or arguments as the basis for the unique cache keys rather than the individual data sets used.

Community
  • 1
  • 1
NeoVance
  • 404
  • 2
  • 9
1

Why not look into and overriding the __toString() method on the object to get and hash the relevant data in the object.

For example

class Object
{
    // Some vars
    public $name = "Jake";
    public $age = 26;
    public $dob = "1/1/10"

    // the toString method
    public function __toString()
    {
         return md5($this->name . $this->age . $this->dob);
    }
}

// Create new object
$object = new Object();

// echo the object, this automatically calls your __toString method
echo $object

In this situation you don't use serialize, which is costly, instead just use __toString() to generate your own unique id based on variables stored with the object.

Jake N
  • 10,535
  • 11
  • 66
  • 112
  • this is what i use now hash('md5',serialize($this->_data)) from inside the class over the stored data, but its a rather costly operation to do so over recordsets, especially if they contain hundrets of records. I was looking for something more low lv for the gain in speed – Paul Scheltema Jan 20 '11 at 09:03
  • the classdata i need serialized is in a datacontainer class, wich gets usually the query results from the db, it has an internal array the $_data wish stores the data, i can iterate the array and merge it to one string, and then md5 that but thats slower than serialize, i use a public method getId() instead of casting the object to string wich is the __toString method for, not to mention the $_data array can contain nested array, wich in your example should be recursively added together to one big string to perform the md5 over, that making the array to string part is the slow part – Paul Scheltema Jan 20 '11 at 13:02
  • I think maybe we need to strip this back to the original issue. Why do you need a unique ID for an object which is maintained between PHP instances/requests? – Jake N Jan 20 '11 at 14:09
  • to be able to tell if the template parsed with the data is in cache, the template key used is ||| – Paul Scheltema Jan 20 '11 at 21:57
  • added some more details to my post, but i still just need to have an unique id of an array, seems so simple doesnt it ^^ alas i cant find how – Paul Scheltema Jan 20 '11 at 22:17