spl_object_hash для PHP <5.2 (уникальный идентификатор для экземпляров объекта)

Я пытаюсь получить уникальные идентификаторы для экземпляров объектов в PHP 5+.

Функция, spl_object_hash() доступна из PHP 5.2, но мне интересно, есть ли временное решение для более старых версий PHP.

В комментариях на php.net есть несколько функций, но они не работают для меня. Первый (упрощенный):

 function spl_object_hash($object){ if (is_object($object)){ return md5((string)$object); } return null; } 

не работает с собственными объектами (такими как DOMDocument), а второй:

 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; } 

похоже, что это может быть серьезный басист производительности!

У кого-нибудь есть что-то в рукаве?

Solutions Collecting From Web of "spl_object_hash для PHP <5.2 (уникальный идентификатор для экземпляров объекта)"

Я провел несколько быстрых тестов. Я действительно думаю, что вам лучше сохранить реальные обратные вызовы в вашей функции bind (), используя bind('evt_name', array($obj, 'callback_function')) . Если вы абсолютно хотите перейти по пути spl_object_hash, вместо того, чтобы хранить ссылки с привязками событий, вы смотрите на что-то вроде этого:

Реализация var_dump / extract и 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; } 

Реализация наивных ссылок:

 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; } 

Это было в основном на 5-50 раз хуже, чем базовая эталонная функция по всему борту, поэтому не стоит беспокоиться.

Ссылки на хранилище по классам:

 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; } 

И вы получите результаты, которые выглядят так . Реферат: реализация ссылок на основе классов лучше всего подходит для n / 50 классов – в лучшем случае ему удается выполнить 1/3 производительности реализации на основе var_dump , и обычно это намного хуже.

Реализация var_dump кажется приемлемой, хотя и не идеальной. Но если вы не делаете слишком много этих поисков, это не будет для вас узким местом. Особенно в качестве резервного для PHP <5.2 boxen.

Однажды я написал вспомогательную функцию для wordpress, которая предлагает один уникальный хеш для каждого объекта, он работает со счетчиком и сохраняет хеш в качестве свойства публичного класса, если он был назначен объекту. Следующий пример демонстрирует это:

 /** * 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; } 

Если вы используете версию PHP 5, вам не нужно передавать параметр по ссылке.

Это то, что вы хотите.

Я исправил очень вероятную ошибку и оптимизировал функцию из bobthecow ответа (который также заимствован из php.net):

 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]; } } 

Он возвращает целое число (обычно в диапазоне до 100), которое является уникальным для любого объекта (подробности см. В этом ответе на то, что вы видите).


PS Я использую эту реализацию в сценарии реального мира здесь

Будет ли uniqid () работать для вашей задачи?