spl_object_hash per PHP < 5.2 (ID univoco per l'oggetto di istanze)
Domanda
Sto cercando di ottenere un unico Id per le istanze di oggetti in PHP 5+.
La funzione, spl_object_hash()
è disponibile da PHP 5.2, ma mi chiedo se c'è una soluzione per le vecchie versioni di PHP.
Ci sono un paio di funzioni di commenti php.net ma non sta lavorando per me.Il primo (semplificato):
function spl_object_hash($object){
if (is_object($object)){
return md5((string)$object);
}
return null;
}
non funziona con gli oggetti nativi, come DOMDocument), e la seconda:
function spl_object_hash($object){
if (is_object($object)){
ob_start();
var_dump($object);
$dump = ob_get_contents();
ob_end_clean();
if (preg_match('/^object\(([a-z0-9_]+)\)\#(\d)+/i', $dump, $match)) {
return md5($match[1] . $match[2]);
}
}
return null;
}
sembra che potrebbe essere una delle principali prestazioni buster!
Qualcuno ha qualcosa nella manica?
Soluzione
Ho eseguito un paio di test rapidi. Credo davvero che si sarebbe meglio memorizzare i callback reali nella vostra funzione bind () utilizzando bind('evt_name', array($obj, 'callback_function'))
. Se si vuole assolutamente andare via spl_object_hash, invece di memorizzare i riferimenti con i binding di eventi, si sta guardando qualcosa di simile:
Un'implementazione var_dump / estratto e hash ID:
function spl_object_hash_var_dump($object){
if (is_object($object)){
ob_start();
var_dump($object);
$dump = ob_get_contents();
ob_end_clean();
if (preg_match('/^object\(([a-z0-9_]+)\)\#(\d)+/i', $dump, $match)) {
return md5($match[1] . $match[2]);
}
}
return null;
}
Un'implementazione riferimenti ingenui:
function spl_object_dumb_references(&$object) {
static $hashes;
if (!isset($hashes)) $hashes = array();
// find existing instance
foreach ($hashes as $hash => $o) {
if ($object === $o) return $hash;
}
$hash = md5(uniqid());
while (array_key_exists($hash, $hashes)) {
$hash = md5(uniqid());
}
$hashes[$hash] = $object;
return $hash;
}
Questa è stata fondamentalmente 5-50x peggiore della funzione di riferimento di classe a base di tutta la linea, quindi non vale la pena preoccuparsi.
un negozio di riferimenti di implementazione della classe:
function spl_object_hash_references(&$object) {
static $hashes;
if (!isset($hashes)) $hashes = array();
$class_name = get_class($object);
if (!array_key_exists($class_name, $hashes)) {
$hashes[$class_name] = array();
}
// find existing instance
foreach ($hashes[$class_name] as $hash => $o) {
if ($object === $o) return $hash;
}
$hash = md5(uniqid($class_name));
while (array_key_exists($hash, $hashes[$class_name])) {
$hash = md5(uniqid($class_name));
}
$hashes[$class_name][$hash] = $object;
return $hash;
}
E si finisce con risultati che assomigliano a questo . Sommario: l'attuazione riferimenti basato classe esegue migliore in circolazione n / 50 classi - al suo meglio, riesce a tirare fuori 1/3 le prestazioni della realizzazione var_dump
based, e di solito è molto peggio <. / p>
L'implementazione var_dump
sembra essere tollerabile, anche se non è l'ideale. Ma se non stai facendo troppi di questi ricerche, non sarà un collo di bottiglia per voi. Soprattutto come ripiego per PHP <5.2 boxen.
Altri suggerimenti
Una volta ho scritto una funzione di supporto per wordpress che offre un hash univoco per ogni oggetto, funziona con un contatore e memorizza il valore hash per come struttura di classe pubblico se è stato assegnato ad un oggetto. L'esempio seguente dimostra questo:
/**
* get object hash
*
* Returns a unique hash per object.
*
* Proxy function for wordpress installments on servers
* with a PHP version < 5.2.0.
*
* @since 3.0.2
* @note Become deprecated with version 3.2.0 (PHP 5.2 requirements)
* @param object $object
* @return string unique object hash
*/
function wp_object_hash( &$object ) {
static $prefix, $count = 0, $property = '__wphookobjhash__', $spl_function_exists;
isset( $spl_function_exists ) || $spl_function_exists = function_exists( 'spl_object_hash' );
// prefer spl_object_hash if available
if ( $spl_function_exists )
return spl_object_hash( $object );
// validate input
if ( !is_object( $object ) ) {
trigger_error( __FUNCTION__ . '() expects parameter 1 to be object', E_USER_WARNING );
return null;
}
// setup prefix and counter to generate object hash, set it to object if not set
isset( $prefix ) || ( ( $prefix = uniqid( '' ) ) && $property .= $prefix . '__' );
isset( $object->$property ) || ( $object->$property = sprintf( '%s-%08d', $prefix , ++$count ) );
return $object->$property;
}
Se si utilizza una versione di PHP 5, non è necessario passare il parametro per riferimento.
Questo è ciò che si desidera.
Ho risolto molto probabile bug e ottimizzato la funzione da bobthecow risposta (che è anche preso in prestito da php.net) a questo:
if ( !function_exists( 'spl_object_hash' ) ) {
function spl_object_hash( $object )
{
ob_start();
var_dump( $object );
preg_match( '[#(\d+)]', ob_get_clean(), $match );
return $match[1];
}
}
Restituisce un numero intero (di solito nel sub-100), che è unico per ogni oggetto (vedere questa risposta per maggiori dettagli su quello che si sta vedendo).
P. S.Io uso questa implementazione in uno scenario reale qui
uniqid () lavoro per il vostro compito?